蓝牙调试工具如何使用
This post is originally from www.jaredwolff.com.
这篇文章最初来自www.jaredwolff.com。
This is Part 2 of configuring your own Bluetooth Low Energy Service using a Nordic NRF52 series processor. If you haven’t seen Part 1 go back and check it out. I’ll be waiting right here..
这是使用Nordic NRF52系列处理器配置自己的低功耗蓝牙服务的第2部分。 如果您还没有看到第1部分,请返回并进行检查。 我将在这里等
If you’re with me thus far, high five. ?
如果到目前为止你和我在一起,高五。 ?
Let’s jump in!
让我们跳进去!
So far we’ve created an efficient cross platform data structure using Protocol Buffers. This Protocol Buffer in particular can be used to send these defined data structures a Bluetooth Low Energy Service. In this part, I’ll show you the inner workings of creating the service from scratch.
到目前为止,我们已经使用协议缓冲区创建了有效的跨平台数据结构。 该协议缓冲区尤其可以用于向这些定义的数据结构发送蓝牙低功耗服务。 在这一部分中,我将向您展示从头开始创建服务的内部工作原理。
P.S. this post is lengthy. If you want something to download, click here for a a beautifully formatted PDF. (Added bonus, the PDF has all three parts of this series!)
PS这个帖子很长。 如果要下载某些内容, 请单击此处以获取格式精美的PDF。 (此外,PDF具有本系列的所有三个部分!)
创建服务 (Creating the Service)
Dealing with Bluetooth Low Energy in general can seem overwhelming. As I discussed here, there’s a few moving parts that you need to keep in mind.
通常,处理低功耗蓝牙似乎不堪重负。 正如我在这里讨论的那样,您需要牢记一些活动部分。
The best way to create a new service is to copy an already existing one! I’ve done this by:
创建新服务的最好方法是复制一个已经存在的服务! 我这样做是:
- Go to the sdk -> components -> ble -> ble_services -> ble_bas 转到sdk->组件-> ble-> ble_services-> ble_bas
Copy
ble_bas.h
toinclude/ble
复制
ble_bas.h
以include/ble
Copy
ble_bas.c
tosrc/ble
将
ble_bas.c
复制到src/ble
I’ve then renamed them from ble_bas
to ble_protobuf
to be consistent. I’ve also done the same inside the files. (BAS is the battery level service used to report battery voltage or relative charge using a percentage)
然后,为了保持一致,我将它们从ble_bas
重命名为ble_protobuf
。 我也在文件内部做了同样的事情。 (BAS是电池电量服务,用于以百分比形式报告电池电压或相对电量)
I’ve also gone ahead and removed all the battery measurement functions as they will be replaced. This part of the process is fairly tedious and prone to error. If you’re new to the Nordic SDK, I highly recommend you download the example code for this post.
我也继续进行并删除了所有电池测量功能,因为它们将被替换。 该过程的这一部分相当繁琐并且容易出错。 如果您是Nordic SDK的新手, 我强烈建议您下载本文的示例代码。
添加UUID (Adding a UUID)
Normally, for a vendor defined service you’ll have to use your own UUID. There are certain ranges of UUIDs that are reserved for the Bluetooth SIG. Supposedly you can also reserve your own UUID if you’re a member. Here’s a handy post on Stack Overflow on the subject.
通常,对于供应商定义的服务,您将必须使用自己的UUID。 有某些范围的UUID保留用于Bluetooth SIG。 如果您是会员,还可以保留自己的UUID。 这是有关该主题的Stack Overflow的便捷文章。
In our case, I’ve defined a UUID that I’ve used for other projects. If you go to ble_protobuf.h
you can see the UUIDs for both the service and the characteristic:
在我们的案例中,我已经定义了用于其他项目的UUID。 如果转到ble_protobuf.h
,则可以看到该服务和特征的UUID:
// UUID for the Service & Char
#define PROTOBUF_UUID_BASE {0x72, 0x09, 0x1a, 0xb3, 0x5f, 0xff, 0x4d, 0xf6, \0x80, 0x62, 0x45, 0x8d, 0x00, 0x00, 0x00, 0x00}
#define PROTOBUF_UUID_SERVICE 0xf510
#define PROTOBUF_UUID_CONFIG_CHAR (PROTOBUF_UUID_SERVICE + 1)
Both PROTOBUF_UUID_BASE
PROTOBUF_UUID_SERVICE
are used in ble_protobuf_init
The last one is used in command_char_add
(I’ll describe that a bit more below).
这两个PROTOBUF_UUID_BASE
PROTOBUF_UUID_SERVICE
在使用ble_protobuf_init
最后一个是在使用command_char_add
(我将介绍更多一点下文)。
You can go without defining a BASE ID but I highly recommend you go the extra mile. That way your application will be impervious to future Bluetooth protocol updates.
您可以在不定义BASE ID的情况下进行操作,但是我强烈建议您多加努力。 这样,您的应用程序将不受以后的蓝牙协议更新的影响。
创建特征 (Creating the Characteristic)
Nordic has a fairly straight forward way of initializing separate characteristics in each service. For each characteristic, there is a char_add
function which then configures and add the characteristic to the service.
Nordic在每种服务中初始化一个单独特征的方法相当简单。 对于每个特征,都有一个char_add
函数,该函数然后配置该特征并将其添加到服务中。
使用ble_add_char_params_t
配置特征 (Configure your Characteristic withble_add_char_params_t
)
Nordic has put the configurations parameters for a BLE Characteristic into a logical (and helpful) struct. If you’re developing on a different platform you may find the same settings though all not in one place! (Or handled logically… ?)
Nordic已将BLE特性的配置参数放入逻辑(且有用)的结构中。 如果您在不同的平台上进行开发,则可能会发现相同的设置,尽管它们都不在一个地方! (或按逻辑处理……?)
Here’s the breakdown of the struct:
这是该结构的细分:
typedef struct
{uint16_t uuid;uint8_t uuid_type;uint16_t max_len;uint16_t init_len;uint8_t * p_init_value;bool is_var_len;ble_gatt_char_props_t char_props;ble_gatt_char_ext_props_t char_ext_props;bool is_defered_read;bool is_defered_write;security_req_t read_access;security_req_t write_access;security_req_t cccd_write_access;bool is_value_user;ble_add_char_user_desc_t *p_user_descr;ble_gatts_char_pf_t *p_presentation_format;
} ble_add_char_params_t;
It’s here that you tell the BLE Stack about what type of characteristic this is. In this example I use a handful of parameters to define the Protobuf Command Characteristic.
您在这里告诉BLE堆栈这是什么类型的特征。 在此示例中,我使用了一些参数来定义Protobuf命令特征。
uuid
defines the address of how the characteristic will be accessed. If you’re defining your own service. max_len
is the maximum length of data that you may send though the characteristic. That’s why it’s important to set max_size
in your Protocol Buffer .options
file for all variable length parameters. Once you compile your Protocol Buffers you’ll get a *_size
variable much like the one defined in command.pb.h
Here's a snippet of what it looks like below:
uuid
定义将如何访问特征的地址。 如果您要定义自己的服务。 max_len
是您可以通过特征发送的最大数据长度。 这就是为什么在Protocol Buffer .options
文件中为所有可变长度参数设置max_size
的原因。 编译协议缓冲区后,您将获得一个*_size
变量,就像在command.pb.h
定义的变量一样。这是下面的代码片段:
/* Maximum encoded size of messages (where known) */
#define event_size 67
Thus when defining ble_add_char_params_t
I set max_len
to event_size
:
因此,在定义ble_add_char_params_t
我将max_len
设置为event_size
:
add_char_params.uuid = PROTOBUF_UUID_CONFIG_CHAR;
add_char_params.max_len = event_size;
add_char_params.is_var_len = true;
Along the same lines, because we’re using a string as one of the parameters in the Protocol Buffer, this data can be of variable size. is_var_len
is handy to make sure that the right amount of bytes is sent and received. The decode function of the Protocol Buffers will fail if more data is fed in than necessary. (I learned this the hard way!)
同样,由于我们使用字符串作为协议缓冲区中的参数之一,因此此数据的大小可以可变。 is_var_len
可以方便地确保发送和接收正确数量的字节。 如果输入的数据超出了必要,协议缓冲区的解码功能将失败。 (我经过惨痛的教训才学到这个!)
char_props
define the permissions for the characteristic. If you’re familiar with file system permissions on a computer, this will be second nature to you. In this example, read and write is what we’re looking for.
char_props
定义特征的权限。 如果您熟悉计算机上的文件系统权限,这将是您的第二天性。 在这个例子中, 读取和写入就是我们要寻找的。
Finally, parameters ending in _access
determine the security type used. In most cases SEC_OPEN
or SEC_JUST_WORKS
is more than sufficient. If you’re handling critical data (passwords, etc) you may have to implement a second layer of encryption or enable a higher level security mode.
最后,以_access
结尾的参数确定所使用的安全性类型。 在大多数情况下, SEC_OPEN
或SEC_JUST_WORKS
。 如果要处理关键数据(密码等),则可能必须实施第二层加密或启用更高级别的安全模式。
If you’re looking on more info about Bluetooth Low Energy security, here’s a useful post on the subject.
如果您正在寻找有关蓝牙低功耗安全性的更多信息, 这是有关此主题的有用文章。
加。 天 字符 (Add. dat. char.)
Once you’ve defined your params, it’s as easy as calling the characteristic_add
function. This will associate this new characteristic with the related service. The first argument is the service handle, the second the configuration parameters and the third is a pointer to the handles for the characteristic. (See below)
定义了参数之后,就像调用characteristic_add
函数一样简单。 这会将这个新特性与相关服务相关联。 第一个参数是服务句柄,第二个参数是配置参数,第三个参数是指向特征句柄的指针。 (见下文)
uint32_t characteristic_add(uint16_t service_handle,ble_add_char_params_t * p_char_props,ble_gatts_char_handles_t * p_char_handle)
使其运行 (Getting it Running)
Setting everything up inside ble_protobuf.c
is 90% of the battle. The final mile requires some bits being added to services_init
in main.c
在ble_protobuf.c
设置所有内容的工作是90%。 最后一英里需要将一些位添加到main.c
services_init
中
ble_protobuf_init_t protobuf_init = {0};protobuf_init.evt_handler = ble_protobuf_evt_hanlder;protobuf_init.bl_rd_sec = SEC_JUST_WORKS;protobuf_init.bl_cccd_wr_sec = SEC_JUST_WORKS;protobuf_init.bl_wr_sec = SEC_JUST_WORKS;err_code = ble_protobuf_init(&m_protobuf,&protobuf_init);APP_ERROR_CHECK(err_code);
The above allows events to be funneled back to the main context. That way your app becomes much more interactive with the core logic of your firmware code. In Nordic’s examples they’ve also brought the security parameters out so they can be defined in the main context as well.
上面的内容使事件可以漏回到主上下文中。 这样,您的应用程序就可以与固件代码的核心逻辑更加互动。 在Nordic的示例中,他们还提出了安全性参数,因此也可以在主要上下文中进行定义。
Side note: m_protobuf
is defined using a macro from ble_protobuf.h
It not only creates a static instance of the service but it also defines the callback that is used for handling events.
附注: m_protobuf
使用宏定义从ble_protobuf.h
它不仅创造了该服务的静态实例,但它也定义了用于处理事件的回调。
/**@brief Macro for defining a ble_protobuf instance.** @param _name Name of the instance.* @hideinitializer*/
#define BLE_PROTOBUF_DEF(_name) \static ble_protobuf_t _name; \NRF_SDH_BLE_OBSERVER(_name ## _obs, \BLE_PROTOBUF_BLE_OBSERVER_PRIO, \ble_protobuf_on_ble_evt, \&_name)
If you're making your own service, you'll have to update the function name for the event handler. If you need to tweak priorities you can define/update that as well.
如果您要提供自己的服务,则必须更新事件处理程序的函数名称。 如果您需要调整优先级,则也可以定义/更新优先级。
写入此特征后会发生什么? (What happens when this characteristic is written to?)
ble_protobuf_on_ble_evt
is the main way that events are handled within Bluetooth Low Energy services. We’re most concerned with the BLE_GATTS_EVT_WRITE
event but you can trigger on any GATT event that tickles your fancy.
ble_protobuf_on_ble_evt
是在蓝牙低功耗服务中处理事件的主要方式。 我们最关心BLE_GATTS_EVT_WRITE
事件,但是您可以触发任何让您BLE_GATTS_EVT_WRITE
GATT事件。
on_write
is where the action happens. It takes the data that is written to the characteristic and decodes it according to event_fields
It’s all put conveniently into a struct for additional processing, etc. If an error happens in decoding, pb_decode
returns an error. Once modified, the data is encoded and made available for reading. Since reading Part 1, the calls to pb_decode
and pb_encode
should look very familiar!
on_write
是执行操作的地方。 它接受写入特征的数据,并根据event_fields
对其进行解码。所有这些都方便地放入结构中以进行其他处理,等等。如果解码中发生错误,则pb_decode
将返回错误。 修改后,数据将被编码并可供读取。 自阅读第1部分以来,对pb_decode
和pb_encode
的调用应该看起来非常熟悉!
Of course, you can have your firmware do whatever you want to. The Bluetooth Energy World is your oyster.
当然,您可以让固件做任何您想做的事情。 蓝牙能源世界是您的牡蛎。
最后说明 (Final Notes)
When adding new services to a Bluetooth Low Energy example, you may have to make some changes to the underlying code.
在向低功耗蓝牙示例添加新服务时,您可能必须对基础代码进行一些更改。
For example, sdk_config.h
may need some changes. Particularly NRF_SDH_BLE_VS_UUID_COUNT
needs to be increased depending how many service UUIDs are made available. For this project, I am also using the DFU service (as it should be a default for all connected projects!!)
例如, sdk_config.h
可能需要进行一些更改。 特别是需要增加NRF_SDH_BLE_VS_UUID_COUNT
,具体取决于有多少个服务UUID可用。 对于这个项目,我还使用了DFU服务(因为它应该是所有连接项目的默认设置!)
Another important aspect is memory and flash management. The default .ld
file that comes with the BLE DFU service may not be sufficient for another BLE Service. The only way you’ll know there’s not enough is when you compile and flash it to a NRF52 device. If the device boots up stating there’s not enough memory, you’ll have to make the suggested changes. The error will show up on the debug console where this message normally shows up:
另一个重要方面是内存和闪存管理。 BLE DFU服务随附的默认.ld
文件可能不足以用于另一个BLE服务。 唯一了解不足的方法是编译并刷新到NRF52设备。 如果设备启动后表明没有足够的内存,则必须进行建议的更改。 该错误将显示在通常显示此消息的调试控制台上:
<info> app: Setting vector table to bootloader: 0x00078000
<info> app: Setting vector table to main app: 0x00026000
Learn more about how to get the Debug Console set up in the example code here.
在此处的示例代码中了解有关如何设置调试控制台的更多信息。
结论 (Conclusion)
In this part I’ve shown you the inner workings of a custom Bluetooth Low Energy service using Protocol Buffers. In the last part, I’ll show you how to load the firmware, run the example javascript app and test our freshly developed Protocol Buffer!
在这一部分中,我向您展示了使用协议缓冲区的自定义低功耗蓝牙服务的内部工作原理。 在最后一部分中,我将向您展示如何加载固件,运行示例javascript应用程序以及测试我们新开发的Protocol Buffer!
翻译自: https://www.freecodecamp.org/news/improve-your-bluetooth-project-with-this-valuable-tool-part-2/
蓝牙调试工具如何使用