Part 1
요약·해설
Bluetooth 초기화부터 identity, scan, connection, legacy·extended·encrypted advertising, Filter Accept List, pairing, GATT, L2CAP, A2DP와 runtime logging까지 공식 command transcript를 그대로 실행할 수 있게 보존합니다.
27 official transcripts
Scan · Connect · Security
GATT · L2CAP · A2DP
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
A1D1624D8E0BCCBC9C842A2D09255735B9DF7F6FF990D8A8D87D6481CA10CFFC
.. _bluetooth_shell:
Shell
#####
The Bluetooth Shell is an application based on the :ref:`shell_api` module. It offer a collection of
commands made to easily interact with the Bluetooth stack.
Bluetooth Shell Setup and Usage
*******************************
First you need to build and flash your board with the Bluetooth shell. For how to do that, see the
:ref:`getting_started`. The Bluetooth shell itself is located in
:zephyr_file:`tests/bluetooth/shell/`.
When it's done, connect to the CLI using your favorite serial terminal application. You should see
the following prompt:
.. code-block:: console
uart:~$
For more details on general usage of the shell, see :ref:`shell_api`.
The first step is enabling Bluetooth. To do so, use the :code:`bt init` command. The following
message is printed to confirm Bluetooth has been initialized.
.. code-block:: console
uart:~$ bt init
Bluetooth initialized
Settings Loaded
[00:02:26.771,148] <inf> fs_nvs: nvs_mount: 8 Sectors of 4096 bytes
[00:02:26.771,148] <inf> fs_nvs: nvs_mount: alloc wra: 0, fe8
[00:02:26.771,179] <inf> fs_nvs: nvs_mount: data wra: 0, 0
[00:02:26.777,984] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
[00:02:26.778,015] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
[00:02:26.778,045] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 3.2 Build 99
[00:02:26.778,656] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load()
[00:02:26.794,738] <inf> bt_hci_core: bt_dev_show_info: Identity: EB:BF:36:26:42:09 (random)
[00:02:26.794,769] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x0000, manufacturer 0x05f1
[00:02:26.794,799] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0xffff
Identities
**********
Identities are a Zephyr host concept, allowing a single physical device to behave like multiple
logical Bluetooth devices.
The shell allows the creation of multiple identities, to a maximum that is set by the Kconfig symbol
:kconfig:option:`CONFIG_BT_ID_MAX`. To create a new identity, use :code:`bt id-create` command. You
can then use it by selecting it with its ID :code:`bt id-select <id>`. Finally, you can list all the
available identities with :code:`id-show`.
Scan for devices
****************
Start scanning by using the :code:`bt scan on` command. Depending on the environment you're in, you
may see a lot of lines printed on the shell. To stop the scan, run :code:`bt scan off`, the
scrolling should stop.
Here is an example of what you can expect:
.. code-block:: console
uart:~$ bt scan on
Bluetooth active scan enabled
[DEVICE]: CB:01:1A:2D:6E:AE (random), AD evt type 0, RSSI -78 C:1 S:1 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 20:C2:EE:59:85:5B (random), AD evt type 3, RSSI -62 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: E3:72:76:87:2F:E8 (random), AD evt type 3, RSSI -74 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 1E:19:25:8A:CB:84 (random), AD evt type 3, RSSI -67 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 26:42:F3:D5:A0:86 (random), AD evt type 3, RSSI -73 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 0C:61:D1:B9:5D:9E (random), AD evt type 3, RSSI -87 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 20:C2:EE:59:85:5B (random), AD evt type 3, RSSI -66 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 25:3F:7A:EE:0F:55 (random), AD evt type 3, RSSI -83 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
uart:~$ bt scan off
Scan successfully stopped
As you can see, this can lead to a high number of results. To reduce that number and easily find a
specific device, you can enable scan filters. There are four types of filters: by name, by RSSI, by
address and by periodic advertising interval. To apply a filter, use the :code:`bt scan-set-filter`
command followed by the type of filters. You can add multiple filters by using the commands again.
For example, if you want to look only for devices with the name *test shell*:
.. code-block:: console
uart:~$ bt scan-filter-set name "test shell"
Or if you want to look for devices at a very close range:
.. code-block:: console
uart:~$ bt scan-filter-set rssi -40
RSSI cutoff set at -40 dB
Finally, if you want to remove all filters:
.. code-block:: console
uart:~$ bt scan-filter-clear all
You can use the command :code:`bt scan on` to create an *active* scanner, meaning that the scanner
will ask the advertisers for more information by sending a *scan request* packet. Alternatively, you
can create a *passive scanner* by using the :code:`bt scan passive` command, so the scanner will not
ask the advertiser for more information.
Connecting to a device
**********************
To connect to a device, you need to know its address and type of address and use the
:code:`bt connect` command with the address and the type as arguments.
Here is an example:
.. code-block:: console
uart:~$ bt connect 52:84:F6:BD:CE:48 random
Connection pending
Connected: 52:84:F6:BD:CE:48 (random)
Remote LMP version 5.3 (0x0c) subversion 0xffff manufacturer 0x05f1
LE Features: 0x000000000001412f
LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
LE conn param req: int (0x0018, 0x0028) lat 0 to 42
LE conn param updated: int 0x0028 lat 0 to 42
You can list the active connections of the shell using the :code:`bt connections` command. The shell
maximum number of connections is defined by :kconfig:option:`CONFIG_BT_MAX_CONN`. You can disconnect
from a connection with the
:code:`bt disconnect <address: XX:XX:XX:XX:XX:XX> <type: (public|random)>` command.
.. note::
If you were scanning just before, you can connect to the last scanned device by
simply running the :code:`bt connect` command.
Alternatively, you can use the :code:`bt connect-name <name>` command to automatically
enable scanning with a name filter and connect to the first match.
Advertising
***********
Begin advertising by using the :code:`bt advertise on` command. This will use the default parameters
and advertise a resolvable private address with the name of the device. You can choose to use the
identity address instead by running the :code:`bt advertise on identity` command. To stop
advertising use the :code:`bt advertise off` command.
To enable more advanced features of advertising, you should create an advertiser using the
:code:`bt adv-create` command. Parameters for the advertiser can be passed either at the creation of
it or by using the :code:`bt adv-param` command. To begin advertising with this newly created
advertiser, use the :code:`bt adv-start` command, and then the :code:`bt adv-stop` command to stop
advertising.
When using the custom advertisers, you can choose if it will be connectable or scannable. This leads
to four options: :code:`conn-scan`, :code:`conn-nscan`, :code:`nconn-scan` and :code:`nconn-nscan`.
Those parameters are mandatory when creating an advertiser or updating its parameters.
For example, if you want to create a connectable and scannable advertiser and start it:
.. code-block:: console
uart:~$ bt adv-create conn-scan
Created adv id: 0, adv: 0x200022f0
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set started
You may notice that with this, the custom advertiser does not advertise the device name; you need to
add it. Continuing from the previous example:
.. code-block:: console
uart:~$ bt adv-stop
Advertiser set stopped
uart:~$ bt adv-data dev-name
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set started
You should now see the name of the device in the advertising data. You can also set a custom name by
using :code:`name <custom name>` instead of :code:`dev-name`. It is also possible to set the
advertising data manually with the :code:`bt adv-data` command. The following example shows how
to set the advertiser name with it using raw advertising data:
.. code-block:: console
uart:~$ bt adv-create conn-scan
Created adv id: 0, adv: 0x20002348
uart:~$ bt adv-data 1009426C7565746F6F74682D5368656C6C
uart:~$ bt adv-start
Advertiser[0] 0x20002348 set started
The data must be formatted according to the Bluetooth Core Specification (see version 5.3, vol. 3,
part C, 11). In this example, the first octet is the size of the data (the data and one octet for
the data type), the second one is the type of data, ``0x09`` is the Complete Local Name and the
remaining data are the name in ASCII. So, on the other device you should see the name
*Bluetooth-Shell*.
When advertising, if others devices use an *active* scanner, you may receive *scan request* packets.
To visualize those packets, you can add :code:`scan-reports` to the parameters of your advertiser.
Directed Advertising
====================
It is possible to use directed advertising on the shell if you want to reconnect to a device. The
following example demonstrates how to create a directed advertiser with the address specified right
after the parameter :code:`directed`. The :code:`low` parameter indicates that we want to use the
low duty cycle mode, and the :code:`dir-rpa` parameter is required if the remote device is
privacy-enabled and supports address resolution of the target address in directed advertisement.
.. code-block:: console
uart:~$ bt adv-create conn-scan directed D7:54:03:CE:F3:B4 random low dir-rpa
Created adv id: 0, adv: 0x20002348
After that, you can start the advertiser and then the target device will be able to reconnect.
Extended Advertising
====================
Let's now have a look at some extended advertising features. To enable extended advertising, use the
`ext-adv` parameter.
.. code-block:: console
uart:~$ bt adv-create conn-nscan ext-adv name-ad
Created adv id: 0, adv: 0x200022f0
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set started
This will create an extended advertiser, that is connectable and non-scannable.
Encrypted Advertising Data
==========================
Zephyr has support for the Encrypted Advertising Data feature. The :code:`bt encrypted-ad`
sub-commands allow managing the advertising data of a given advertiser.
To encrypt the advertising data, key materials need to be provided, that can be done with :code:`bt
encrypted-ad set-keys <session key> <init vector>`. The session key is 16 bytes long and the
initialisation vector is 8 bytes long.
You can add advertising data by using :code:`bt encrypted-ad add-ad` and :code:`bt encrypted-ad
add-ead`. The former will take add one advertising data structure (as defined in the Core
Specification), when the later will read the given data, encrypt them and then add the generated
encrypted advertising data structure. It's possible to mix encrypted and non-encrypted data, when
done adding advertising data, :code:`bt encrypted-ad commit-ad` can be used to apply the change to
the data to the selected advertiser. After that the advertiser can be started as described
previously. It's possible to clear the advertising data by using :code:`bt encrypted-ad clear-ad`.
On the Central side, it's possible to decrypt the received encrypted advertising data by setting the
correct keys material as described earlier and then enabling the decrypting of the data with
:code:`bt encrypted-ad decrypt-scan on`.
.. note::
To see the advertising data in the scan report :code:`bt scan-verbose-output` need to be
enabled.
.. note::
It's possible to increase the length of the advertising data by increasing the value of
:kconfig:option:`CONFIG_BT_CTLR_ADV_DATA_LEN_MAX` and
:kconfig:option:`CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX`.
Here is a simple example demonstrating the usage of EAD:
.. tabs::
.. group-tab:: Peripheral
.. code-block:: console
uart:~$ bt init
...
uart:~$ bt adv-create conn-nscan ext-adv
Created adv id: 0, adv: 0x81769a0
uart:~$ bt encrypted-ad set-keys 9ba22d3824efc70feb800c80294cba38 2e83f3d4d47695b6
session key set to:
00000000: 9b a2 2d 38 24 ef c7 0f eb 80 0c 80 29 4c ba 38 |..-8$... ....)L.8|
initialisation vector set to:
00000000: 2e 83 f3 d4 d4 76 95 b6 |.....v.. |
uart:~$ bt encrypted-ad add-ad 06097368656C6C
uart:~$ bt encrypted-ad add-ead 03ffdead03ffbeef
uart:~$ bt encrypted-ad commit-ad
Advertising data for Advertiser[0] 0x81769a0 updated.
uart:~$ bt adv-start
Advertiser[0] 0x81769a0 set started
.. group-tab:: Central
.. code-block:: console
uart:~$ bt init
...
uart:~$ bt scan-verbose-output on
uart:~$ bt encrypted-ad set-keys 9ba22d3824efc70feb800c80294cba38 2e83f3d4d47695b6
session key set to:
00000000: 9b a2 2d 38 24 ef c7 0f eb 80 0c 80 29 4c ba 38 |..-8$... ....)L.8|
initialisation vector set to:
00000000: 2e 83 f3 d4 d4 76 95 b6 |.....v.. |
uart:~$ bt encrypted-ad decrypt-scan on
Received encrypted advertising data will now be decrypted using provided key materials.
uart:~$ bt scan on
Bluetooth active scan enabled
[DEVICE]: 68:49:30:68:49:30 (random), AD evt type 5, RSSI -59 shell C:1 S:0 D:0 SR:0 E:1 Prim: LE 1M, Secn: LE 2M, Interval: 0x0000 (0 us), SID: 0x0
[SCAN DATA START - EXT_ADV]
Type 0x09: shell
Type 0x31: Encrypted Advertising Data: 0xe2, 0x17, 0xed, 0x04, 0xe7, 0x02, 0x1d, 0xc9, 0x40, 0x07, uart:~0x18, 0x90, 0x6c, 0x4b, 0xfe, 0x34, 0xad
[START DECRYPTED DATA]
Type 0xff: 0xde, 0xad
Type 0xff: 0xbe, 0xef
[END DECRYPTED DATA]
[SCAN DATA END]
...
Filter Accept List
******************
It's possible to create a list of allowed addresses that can be used to
connect to those addresses automatically. Here is how to do it:
.. code-block:: console
uart:~$ bt fal-add 47:38:76:EA:29:36 random
uart:~$ bt fal-add 66:C8:80:2A:05:73 random
uart:~$ bt fal-connect on
The shell will then connect to the first available device. In the example, if both devices are
advertising at the same time, we will connect to the first address added to the list.
The Filter Accept List can also be used for scanning or advertising by using the option :code:`fal`.
For example, if we want to scan for a bunch of selected addresses, we can set up a Filter Accept
List:
.. code-block:: console
uart:~$ bt fal-add 65:4B:9E:83:AF:73 random
uart:~$ bt fal-add 73:72:82:B4:8F:B9 random
uart:~$ bt fal-add 5D:85:50:1C:72:64 random
uart:~$ bt scan on fal
You should see only those three addresses reported by the scanner.
Enabling security
*****************
When connected to a device, you can enable multiple levels of security, here is the list for
Bluetooth LE:
* **1** No encryption and no authentication;
* **2** Encryption and no authentication;
* **3** Encryption and authentication;
* **4** Bluetooth LE Secure Connection.
To enable security, use the :code:`bt security <level>` command. For levels requiring authentication
(level 3 and above), you must first set the authentication method. To do it, you can use the
:code:`bt auth all` command. After that, when you will set the security level, you will be asked to
confirm the passkey on both devices. On the shell side, do it with the command
:code:`bt auth-passkey-confirm`.
Pairing
=======
Enabling authentication requires the devices to be bondable. By default the shell is bondable. You
can make the shell not bondable using :code:`bt bondable off`. You can list all the devices you are
paired with using the command :code:`bt bonds`.
The maximum number of paired devices is set using :kconfig:option:`CONFIG_BT_MAX_PAIRED`. You can
remove a paired device using :code:`bt clear <address: XX:XX:XX:XX:XX:XX> <type: (public|random)>`
or remove all paired devices with the command :code:`bt clear all`.
GATT
****
The following examples assume that you have two devices already connected.
To perform service discovery on the client side, use the :code:`gatt discover` command. This should
print all the services that are available on the GATT server.
On the server side, you can register pre-defined test services using the :code:`gatt register`
command. When done, you should see the newly added services on the client side when running the
discovery command.
You can now subscribe to those new services on the client side. Here is an example on how to
subscribe to the test service:
.. code-block:: console
uart:~$ gatt subscribe 26 25
Subscribed
The server can now notify the client with the command :code:`gatt notify`.
Another option available through the GATT command is initiating the MTU exchange. To do it, use the
:code:`gatt exchange-mtu` command. To update the shell maximum MTU, you need to update Kconfig
symbols in the configuration file of the shell. For more details, see
:ref:`bluetooth_mtu_update_sample`.
L2CAP
*****
The :code:`l2cap` command exposes parts of the L2CAP API. The following example shows how to
register a LE PSM, connect to it from another device and send 3 packets of 14 octets each.
The example assumes that the two devices are already connected.
On device A, register the LE PSM:
.. code-block:: console
uart:~$ l2cap register 29
L2CAP psm 41 sec_level 1 registered
On device B, connect to the registered LE PSM and send data:
.. code-block:: console
uart:~$ l2cap connect 29
Chan sec: 1
L2CAP connection pending
Channel 0x20000210 connected
Channel 0x20000210 status 1
uart:~$ l2cap send 3 14
Rem 2
Rem 1
Rem 0
Outgoing data channel 0x20000210 transmitted
Outgoing data channel 0x20000210 transmitted
Outgoing data channel 0x20000210 transmitted
On device A, you should have received the data:
.. code-block:: console
Incoming conn 0x20002398
Channel 0x20000210 status 1
Channel 0x20000210 connected
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |
A2DP
*****
The :code:`a2dp` command exposes parts of the A2DP API.
The following examples assume that you have two devices already connected.
Here is a example connecting two devices:
* Source and Sink sides register a2dp callbacks. using :code:`a2dp register_cb`.
* Source and Sink sides register stream endpoints. using :code:`a2dp register_ep source sbc` and :code:`a2dp register_ep sink sbc`.
* Source establish A2dp connection. It will create the AVDTP Signaling and Media L2CAP channels. using :code:`a2dp connect`.
* Source and Sink side can discover remote device's stream endpoints. using :code:`a2dp discover_peer_eps`
* Source or Sink configure the stream to create the stream after discover remote's endpoints. using :code:`a2dp configure`.
* Source or Sink establish the stream. using :code:`a2dp establish`.
* Source or Sink start the media. using :code:`a2dp start`.
* Source test the media sending. using :code:`a2dp send_media` to send one test packet data.
.. tabs::
.. group-tab:: Device A (Audio Source Side)
.. code-block:: console
uart:~$ a2dp register_cb
success
uart:~$ a2dp register_ep source sbc
SBC source endpoint is registered
uart:~$ a2dp connect
Bonded with XX:XX:XX:XX:XX:XX
Security changed: XX:XX:XX:XX:XX:XX level 2
a2dp connected
uart:~$ a2dp discover_peer_eps
endpoint id: 1, (sink), (idle):
codec type: SBC
sample frequency:
44100
48000
channel mode:
Mono
Stereo
Joint-Stereo
Block Length:
16
Subbands:
8
Allocation Method:
Loudness
Bitpool Range: 18 - 35
uart:~$ a2dp configure
success to configure
stream configured
uart:~$ a2dp establish
success to establish
stream established
uart:~$ a2dp start
success to start
stream started
uart:~$ a2dp send_media
frames num: 1, data length: 160
data: 1, 2, 3, 4, 5, 6 ......
.. group-tab:: Device B (Audio Sink Side)
.. code-block:: console
uart:~$ a2dp register_cb
success
uart:~$ a2dp register_ep sink sbc
SBC sink endpoint is registered
<after a2dp connect>
Connected: XX:XX:XX:XX:XX:XX
Bonded with XX:XX:XX:XX:XX:XX
Security changed: XX:XX:XX:XX:XX:XX level 2
a2dp connected
<after a2dp configure of source side>
receive requesting config and accept
SBC configure success
sample rate 44100Hz
stream configured
<after a2dp establish of source side>
receive requesting establishment and accept
stream established
<after a2dp start of source side>
receive requesting start and accept
stream started
<after a2dp send_media of source side>
received, num of frames: 1, data length: 160
data: 1, 2, 3, 4, 5, 6 ......
...
Logging
*******
You can configure the logging level per module at runtime. This depends on the maximum logging level
that is compiled in. To configure, use the :code:`log` command. Here are some examples:
* List the available modules and their current logging level
.. code-block:: console
uart:~$ log status
* Disable logging for *bt_hci_core*
.. code-block:: console
uart:~$ log disable bt_hci_core
* Enable error logs for *bt_att* and *bt_smp*
.. code-block:: console
uart:~$ log enable err bt_att bt_smp
* Disable logging for all modules
.. code-block:: console
uart:~$ log disable
* Enable warning logs for all modules
.. code-block:: console
uart:~$ log enable wrn
Part 3
한국어 전문 번역
Bluetooth Shell
Bluetooth Shell은 Zephyr Shell API module을 바탕으로 만든 application입니다. Bluetooth stack과 쉽게 상호작용할 수 있는 command 모음을 제공합니다.
Bluetooth Shell 설정과 사용
먼저 board에 Bluetooth Shell을 build하고 flash합니다. 일반 build·flash 방법은 Getting Started 절을 따르며 Bluetooth Shell source는 tests/bluetooth/shell/에 있습니다.
작업이 끝나면 선호하는 serial terminal application으로 CLI에 연결합니다. 다음 prompt가 나타납니다.
uart:~$Shell의 일반 사용법은 Shell API 문서를 참고합니다.
첫 단계는 Bluetooth 활성화입니다. bt init command를 실행하면 초기화 완료를 확인하는 다음 message가 출력됩니다.
uart:~$ bt init
Bluetooth initialized
Settings Loaded
[00:02:26.771,148] <inf> fs_nvs: nvs_mount: 8 Sectors of 4096 bytes
[00:02:26.771,148] <inf> fs_nvs: nvs_mount: alloc wra: 0, fe8
[00:02:26.771,179] <inf> fs_nvs: nvs_mount: data wra: 0, 0
[00:02:26.777,984] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
[00:02:26.778,015] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
[00:02:26.778,045] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 3.2 Build 99
[00:02:26.778,656] <inf> bt_hci_core: bt_init: No ID address. App must call settings_load()
[00:02:26.794,738] <inf> bt_hci_core: bt_dev_show_info: Identity: EB:BF:36:26:42:09 (random)
[00:02:26.794,769] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x0000, manufacturer 0x05f1
[00:02:26.794,799] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0xffffIdentities
Identity는 한 물리 장치가 여러 논리 Bluetooth 장치처럼 동작하게 하는 Zephyr Host concept입니다.
Shell은 여러 identity를 만들 수 있으며 최대 개수는 CONFIG_BT_ID_MAX로 정합니다. bt id-create로 새 identity를 만들고 bt id-select <id>로 선택합니다. 사용 가능한 identity 전체는 id-show로 표시합니다.
장치 Scan
bt scan on으로 scan을 시작합니다. 주변 환경에 따라 많은 줄이 출력될 수 있습니다. bt scan off를 실행하면 scan과 출력이 멈춥니다.
uart:~$ bt scan on
Bluetooth active scan enabled
[DEVICE]: CB:01:1A:2D:6E:AE (random), AD evt type 0, RSSI -78 C:1 S:1 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 20:C2:EE:59:85:5B (random), AD evt type 3, RSSI -62 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: E3:72:76:87:2F:E8 (random), AD evt type 3, RSSI -74 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 1E:19:25:8A:CB:84 (random), AD evt type 3, RSSI -67 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 26:42:F3:D5:A0:86 (random), AD evt type 3, RSSI -73 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 0C:61:D1:B9:5D:9E (random), AD evt type 3, RSSI -87 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 20:C2:EE:59:85:5B (random), AD evt type 3, RSSI -66 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
[DEVICE]: 25:3F:7A:EE:0F:55 (random), AD evt type 3, RSSI -83 C:0 S:0 D:0 SR:0 E:0 Prim: LE 1M, Secn: No packets, Interval: 0x0000 (0 us), SID: 0xff
uart:~$ bt scan off
Scan successfully stopped결과가 너무 많으면 scan filter로 특정 장치를 쉽게 찾을 수 있습니다. Filter 종류는 name, RSSI, address, periodic advertising interval 네 가지입니다. bt scan-filter-set 뒤에 filter type과 값을 주며 command를 반복해 filter 여러 개를 추가할 수 있습니다.
이름이 test shell인 장치만 찾는 예입니다.
uart:~$ bt scan-filter-set name "test shell"아주 가까운 장치만 찾으려면 RSSI cutoff를 설정합니다.
uart:~$ bt scan-filter-set rssi -40
RSSI cutoff set at -40 dB모든 filter를 지우는 예입니다.
uart:~$ bt scan-filter-clear allbt scan on은 advertiser에 scan request packet을 보내 추가 정보를 요청하는 active scanner를 만듭니다. 추가 정보를 요청하지 않는 passive scanner는 bt scan passive로 만듭니다.
장치 연결
장치에 연결하려면 address와 address type을 알아야 합니다. bt connect에 두 값을 argument로 전달합니다.
uart:~$ bt connect 52:84:F6:BD:CE:48 random
Connection pending
Connected: 52:84:F6:BD:CE:48 (random)
Remote LMP version 5.3 (0x0c) subversion 0xffff manufacturer 0x05f1
LE Features: 0x000000000001412f
LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
LE conn param req: int (0x0018, 0x0028) lat 0 to 42
LE conn param updated: int 0x0028 lat 0 to 42bt connections로 Shell의 active connection을 나열합니다. 최대 connection 수는 CONFIG_BT_MAX_CONN으로 정합니다. bt disconnect <address: XX:XX:XX:XX:XX:XX> <type: (public|random)>로 연결을 끊습니다.
Advertising
bt advertise on은 기본 parameter로 advertising을 시작하며 장치 이름과 resolvable private address를 알립니다. Identity address를 쓰려면 bt advertise on identity, 멈추려면 bt advertise off를 실행합니다.
고급 advertising 기능은 bt adv-create로 advertiser를 만들어 사용합니다. Parameter는 만들 때 전달하거나 bt adv-param으로 설정할 수 있습니다. 새 advertiser는 bt adv-start로 시작하고 bt adv-stop으로 멈춥니다.
Custom advertiser는 connectable·scannable 여부를 조합합니다. 가능한 필수 parameter는 conn-scan, conn-nscan, nconn-scan, nconn-nscan 네 가지입니다.
Connectable·scannable advertiser를 만들고 시작하는 예입니다.
uart:~$ bt adv-create conn-scan
Created adv id: 0, adv: 0x200022f0
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set started이 custom advertiser는 기본적으로 장치 이름을 advertising하지 않습니다. 앞 예에 이어 이름을 추가합니다.
uart:~$ bt adv-stop
Advertiser set stopped
uart:~$ bt adv-data dev-name
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set starteddev-name 대신 name <custom name>으로 custom name을 설정할 수 있습니다. bt adv-data에 raw advertising data를 직접 줄 수도 있습니다.
uart:~$ bt adv-create conn-scan
Created adv id: 0, adv: 0x20002348
uart:~$ bt adv-data 1009426C7565746F6F74682D5368656C6C
uart:~$ bt adv-start
Advertiser[0] 0x20002348 set startedData 형식은 Bluetooth Core Specification 5.3, Volume 3, Part C, 11을 따릅니다. 예의 첫 octet은 data type 1 octet을 포함한 data size이고, 두 번째 octet 0x09는 Complete Local Name type이며, 나머지는 ASCII 이름입니다. 상대 장치에는 Bluetooth-Shell이 보입니다.
상대가 active scanner이면 advertising 중 scan request packet을 받을 수 있습니다. Packet을 보려면 advertiser parameter에 scan-reports를 추가합니다.
Directed Advertising
장치에 재연결하려면 directed advertising을 사용할 수 있습니다. directed 바로 뒤에 target address를 지정합니다. low는 low duty-cycle mode를 뜻하고, 상대가 privacy를 사용하며 directed advertisement target address resolution을 지원하면 dir-rpa가 필요합니다.
uart:~$ bt adv-create conn-scan directed D7:54:03:CE:F3:B4 random low dir-rpa
Created adv id: 0, adv: 0x20002348그 뒤 advertiser를 시작하면 target 장치가 재연결할 수 있습니다.
Extended Advertising
ext-adv parameter로 extended advertising을 활성화합니다.
uart:~$ bt adv-create conn-nscan ext-adv name-ad
Created adv id: 0, adv: 0x200022f0
uart:~$ bt adv-start
Advertiser[0] 0x200022f0 set started이 command는 connectable이며 non-scannable인 extended advertiser를 만듭니다.
Encrypted Advertising Data
Zephyr는 Encrypted Advertising Data(EAD)를 지원합니다. bt encrypted-ad subcommand로 선택 advertiser의 advertising data를 관리합니다.
bt encrypted-ad set-keys <session key> <init vector>로 key material을 제공합니다. Session key는 16 byte, initialization vector는 8 byte입니다.
bt encrypted-ad add-ad는 Core Specification 형식의 일반 advertising data structure 하나를 추가합니다. bt encrypted-ad add-ead는 입력 data를 암호화하고 생성한 encrypted advertising data structure를 추가합니다. 암호화 data와 비암호화 data를 섞을 수 있습니다.
bt encrypted-ad commit-ad로 변경을 선택 advertiser에 반영한 뒤 앞서 설명한 방식으로 advertiser를 시작합니다. bt encrypted-ad clear-ad는 advertising data를 지웁니다. Central에서는 같은 key material을 설정한 뒤 bt encrypted-ad decrypt-scan on으로 수신 EAD 복호화를 켭니다.
다음은 Peripheral이 EAD를 만들고 Central이 같은 key로 scan data를 복호화하는 전체 예입니다.
Peripheral
uart:~$ bt init
...
uart:~$ bt adv-create conn-nscan ext-adv
Created adv id: 0, adv: 0x81769a0
uart:~$ bt encrypted-ad set-keys 9ba22d3824efc70feb800c80294cba38 2e83f3d4d47695b6
session key set to:
00000000: 9b a2 2d 38 24 ef c7 0f eb 80 0c 80 29 4c ba 38 |..-8$... ....)L.8|
initialisation vector set to:
00000000: 2e 83 f3 d4 d4 76 95 b6 |.....v.. |
uart:~$ bt encrypted-ad add-ad 06097368656C6C
uart:~$ bt encrypted-ad add-ead 03ffdead03ffbeef
uart:~$ bt encrypted-ad commit-ad
Advertising data for Advertiser[0] 0x81769a0 updated.
uart:~$ bt adv-start
Advertiser[0] 0x81769a0 set startedCentral
uart:~$ bt init
...
uart:~$ bt scan-verbose-output on
uart:~$ bt encrypted-ad set-keys 9ba22d3824efc70feb800c80294cba38 2e83f3d4d47695b6
session key set to:
00000000: 9b a2 2d 38 24 ef c7 0f eb 80 0c 80 29 4c ba 38 |..-8$... ....)L.8|
initialisation vector set to:
00000000: 2e 83 f3 d4 d4 76 95 b6 |.....v.. |
uart:~$ bt encrypted-ad decrypt-scan on
Received encrypted advertising data will now be decrypted using provided key materials.
uart:~$ bt scan on
Bluetooth active scan enabled
[DEVICE]: 68:49:30:68:49:30 (random), AD evt type 5, RSSI -59 shell C:1 S:0 D:0 SR:0 E:1 Prim: LE 1M, Secn: LE 2M, Interval: 0x0000 (0 us), SID: 0x0
[SCAN DATA START - EXT_ADV]
Type 0x09: shell
Type 0x31: Encrypted Advertising Data: 0xe2, 0x17, 0xed, 0x04, 0xe7, 0x02, 0x1d, 0xc9, 0x40, 0x07, uart:~0x18, 0x90, 0x6c, 0x4b, 0xfe, 0x34, 0xad
[START DECRYPTED DATA]
Type 0xff: 0xde, 0xad
Type 0xff: 0xbe, 0xef
[END DECRYPTED DATA]
[SCAN DATA END]
...Filter Accept List
허용할 address 목록을 만들고 그 address에 자동 연결할 수 있습니다.
uart:~$ bt fal-add 47:38:76:EA:29:36 random
uart:~$ bt fal-add 66:C8:80:2A:05:73 random
uart:~$ bt fal-connect onShell은 사용 가능한 첫 장치에 연결합니다. 예의 두 장치가 동시에 advertising하면 list에 먼저 추가한 address에 연결합니다.
fal option을 사용하면 Filter Accept List를 scan이나 advertising에도 적용할 수 있습니다. 선택한 address만 scan하는 예입니다.
uart:~$ bt fal-add 65:4B:9E:83:AF:73 random
uart:~$ bt fal-add 73:72:82:B4:8F:B9 random
uart:~$ bt fal-add 5D:85:50:1C:72:64 random
uart:~$ bt scan on falScanner에는 세 address만 보고됩니다.
Security 활성화
연결한 장치에 Bluetooth LE security level을 설정할 수 있습니다.
- 1: Encryption·authentication 없음
- 2: Encryption만 있고 authentication 없음
- 3: Encryption과 authentication
- 4: Bluetooth LE Secure Connection
bt security <level>로 level을 설정합니다. Authentication이 필요한 level 3 이상은 먼저 bt auth all로 authentication method를 정해야 합니다. 그 뒤 security level을 설정하면 양쪽 장치에서 passkey 확인을 요구하며 Shell에서는 bt auth-passkey-confirm으로 승인합니다.
Pairing
Authentication을 사용하려면 장치가 bondable이어야 합니다. Shell은 기본적으로 bondable이며 bt bondable off로 끌 수 있습니다. bt bonds는 pairing한 장치를 나열합니다.
Pairing 장치 최대 수는 CONFIG_BT_MAX_PAIRED입니다. bt clear <address: XX:XX:XX:XX:XX:XX> <type: (public|random)>로 특정 장치를, bt clear all로 모든 pairing 장치를 제거합니다.
GATT
다음 예는 두 장치가 이미 연결됐다고 가정합니다.
gatt discover로 client에서 service discovery를 수행하면 GATT server가 제공하는 service가 모두 출력됩니다.
gatt register로 server에 미리 정의한 test service를 등록합니다. 그 뒤 client에서 discovery를 다시 실행하면 새 service가 보입니다.
Client가 test service를 subscribe하는 예입니다.
uart:~$ gatt subscribe 26 25
SubscribedServer는 gatt notify로 client에 notification을 보낼 수 있습니다. gatt exchange-mtu는 MTU exchange를 시작합니다. Shell 최대 MTU를 바꾸려면 Shell configuration file의 Kconfig symbol을 수정하며 자세한 내용은 Bluetooth MTU Update sample을 참고합니다.
L2CAP
l2cap command는 L2CAP API 일부를 노출합니다. 다음 예는 두 장치가 이미 연결된 상태에서 LE PSM을 등록하고 다른 장치가 연결한 뒤 14 octet packet 세 개를 보내는 과정입니다.
Device A에서 LE PSM을 등록합니다.
uart:~$ l2cap register 29
L2CAP psm 41 sec_level 1 registeredDevice B에서 등록된 LE PSM에 연결하고 data를 보냅니다.
uart:~$ l2cap connect 29
Chan sec: 1
L2CAP connection pending
Channel 0x20000210 connected
Channel 0x20000210 status 1
uart:~$ l2cap send 3 14
Rem 2
Rem 1
Rem 0
Outgoing data channel 0x20000210 transmitted
Outgoing data channel 0x20000210 transmitted
Outgoing data channel 0x20000210 transmittedDevice A에는 다음 data가 수신됩니다.
Incoming conn 0x20002398
Channel 0x20000210 status 1
Channel 0x20000210 connected
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |
Channel 0x20000210 requires buffer
Incoming data channel 0x20000210 len 14
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... |A2DP
a2dp command는 A2DP API 일부를 노출합니다. 다음 절차는 두 장치가 이미 연결됐다고 가정합니다.
- Source와 Sink에서
a2dp register_cb로 A2DP callback을 등록합니다. - Source·Sink stream endpoint를
a2dp register_ep source sbc와a2dp register_ep sink sbc로 등록합니다. - Source가
a2dp connect로 A2DP connection을 만들며 AVDTP Signaling·Media L2CAP channel이 생성됩니다. - 양쪽에서
a2dp discover_peer_eps로 상대 stream endpoint를 discovery합니다. a2dp configure로 상대 endpoint를 바탕으로 stream을 구성합니다.a2dp establish로 stream을 수립하고a2dp start로 media를 시작합니다.- Source가
a2dp send_media로 test packet 하나를 보냅니다.
Device A: Audio Source
uart:~$ a2dp register_cb
success
uart:~$ a2dp register_ep source sbc
SBC source endpoint is registered
uart:~$ a2dp connect
Bonded with XX:XX:XX:XX:XX:XX
Security changed: XX:XX:XX:XX:XX:XX level 2
a2dp connected
uart:~$ a2dp discover_peer_eps
endpoint id: 1, (sink), (idle):
codec type: SBC
sample frequency:
44100
48000
channel mode:
Mono
Stereo
Joint-Stereo
Block Length:
16
Subbands:
8
Allocation Method:
Loudness
Bitpool Range: 18 - 35
uart:~$ a2dp configure
success to configure
stream configured
uart:~$ a2dp establish
success to establish
stream established
uart:~$ a2dp start
success to start
stream started
uart:~$ a2dp send_media
frames num: 1, data length: 160
data: 1, 2, 3, 4, 5, 6 ......Device B: Audio Sink
uart:~$ a2dp register_cb
success
uart:~$ a2dp register_ep sink sbc
SBC sink endpoint is registered
<after a2dp connect>
Connected: XX:XX:XX:XX:XX:XX
Bonded with XX:XX:XX:XX:XX:XX
Security changed: XX:XX:XX:XX:XX:XX level 2
a2dp connected
<after a2dp configure of source side>
receive requesting config and accept
SBC configure success
sample rate 44100Hz
stream configured
<after a2dp establish of source side>
receive requesting establishment and accept
stream established
<after a2dp start of source side>
receive requesting start and accept
stream started
<after a2dp send_media of source side>
received, num of frames: 1, data length: 160
data: 1, 2, 3, 4, 5, 6 ......
...Logging
Compile할 때 포함한 최대 logging level 범위 안에서 module별 logging level을 runtime에 바꿀 수 있습니다. log command를 사용합니다.
사용 가능한 module과 현재 logging level 나열:
uart:~$ log statusbt_hci_core logging 끄기:
uart:~$ log disable bt_hci_corebt_att와 bt_smp의 error log 켜기:
uart:~$ log enable err bt_att bt_smp모든 module logging 끄기:
uart:~$ log disable모든 module warning log 켜기:
uart:~$ log enable wrn
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.