EdgeX Foundry 开发设备服务的几个关键点
EdgeX Foundry 开发设备服务的几个关键点
EdgeX Foundry 设备服务是与传感器/设备或物联网对象 (“物”) 交互的边缘连接器,它需要与各种设备交互,将数据传输到边缘计算系统,并根据需求执行控制命令。EdgeX Foundry 通过其模块化设计和丰富的工具集,使得设备服务的开发变得更加简单高效。我们还可以使用设备服务 SDK 来创建您自己的 EdgeX 设备服务,本文重点介绍使用 C-SDK 开发设备服务源代码的几个必须明确的关键点 。
1.设备服务工作流
以 设备服务 template.c 为例,作为一个虚拟设备服务,它可以将数据发送到核心数据微服务,用户可以通过命令和控制微服务发送命令并获得响应,虚拟设备服务的这些功能在执行功能或性能测试时不需要任何实际设备就可以使用。
注意点:
- 虚拟设备服务对核心数据和元数据微服务具有依赖性,因为初始化过程需要检查或注册配置文件,设备和值描述符,因此,核心数据和元数据服务必须在设备服务初始化之前完全启动。
- 服务启动时,服务会通过从 YAML 文件加载“值描述符”,“设备服务”,“设备描述”来初始化,并登记在元数据微服务中,YAML文件默认存在,也可以自行创建。虚拟设备服务为元数据微服务提供回调API来管理设备实例。
2.设备服务示例模板
2.1 SDK 相关工作流
EdgeX Foundry 的 C-SDK 提供了一个设备服务模板(位于 examples/template.c 强烈推荐先看一遍代码),它提供了一套规范化的开发示例,包括自定义回调函数、设备服务启动关闭、内存开辟释放等,是我们初次接触设备服务开发的良好开端。设备服务工作流在上一节有了一个大致的介绍,结合官方的指导文档 servicewritersguide.md (强烈推荐先阅读一遍),这里进一步描述设备服务内部 SDK 相关的工作流,展示如下:
从根本上说,设备服务由多个回调组成,上图中的 SDK 内部工作流均在一系列回调函数中作处理。一个设备服务只有一个设备服务实例结构体指针 Implementation
每次调用回调时,该指针都会被传递,如初始化回调函数的第一个参数 (template_driver *) impl
。
/* --- template.c ---- */
/* Initialize performs protocol-specific initialization for the device
* service.
*/
static bool template_init
(
void *impl,
struct iot_logger_t *lc,
const iot_data_t *config
)
{
template_driver *driver = (template_driver *) impl;
iot_log_debug (lc, "Template Init.");
return true;
}
2.2 template.c 的细节
-
一个设备服务必须要自定义好的回调函数如下:每一个回调函数的实现正如上面提到的
template_init
那样。/* Device Callbacks */ devsdk_callbacks *templateImpls = devsdk_callbacks_init ( template_init, template_get_handler, template_put_handler, template_stop, template_create_addr, template_free_addr, template_create_resource_attr, template_free_resource_attr );
-
同时设备服务 SDK 还提供了一些非必要的回调函数,以便于开发者实现更灵活的需求,在 servicewritersguide.md 的
Optional handlers
部分有提到。举一个例子,一个设备服务实例可以实现device_added
、device_updated
和device_removed
处理程序,然后它将收到服务管理的设备范围的更改通知。如果需要特殊的初始化/关闭操作来优化设备的使用,这可能会有所帮助。只需要将该函数实现,并注册进设备服务的回调初始化函数即可://device_added 的具体实现 static void device_added( void *impl, const char *devname, const devsdk_protocols *protocols, const devsdk_device_resources *resources, bool adminEnabled) { openvino_driver *driver = (openvino_driver *)impl; iot_log_info(driver->lc, "New device added: %s", devname); } ... //主函数内的回调初始化 devsdk_callbacks *templateImpls = devsdk_callbacks_init ( template_init, template_get_handler, template_put_handler, template_stop, template_create_addr, template_free_addr, template_create_resource_attr, template_free_resource_attr ); //注册自定义的设备服务回调 devsdk_callbacks_set_listeners(templateImpls, device_added, NULL, NULL);
3.删除设备的处理逻辑
- 每删除一个设备,一定依次进入的回调函数是:
template_free_resource_attr
和template_free_addr
。 - 如果自定义回调
device_removed
已经初始化,则会优先进入该回调,然后再进入上面两个默认的释放内存处理回调之中。
4.增加设备
4.1 增加设备的方式
- 通过 EdgeX Foundry 官方 UI 界面(如下图所示)增加一个具体的设备,通过界面可视化引导,很容易完成以下步骤:
- SelectDeviceService
- SelectDeviceProfile
- DevicePrimary
- CreateAutoEvent
- CreateDeviceProtocol
注意点:CreateDeviceProtocol 为必须设置项,且需要跟自己的设备服务所规定的协议保持一致。
-
通过 API 控制命令,直接向
core-metadata
发送 POST 请求,即可一行命令生成新设备,如下所示:curl http://localhost:59881/api/v3/device -H "Content-Type: application/json" -X POST \ -d '[ { "apiVersion" : "v3", "device": { "name": "Device1", "description": "An Example Device", "adminState": "UNLOCKED", "operatingState": "UP", "serviceName": "device-template", "profileName": "template", "protocols": { "Others": { "key1": "xxxx", "key2": "yyyy", } } } } ]'
4.2 增加设备的处理逻辑
- 每增加一个设备,会先调用自定义回调
device_add
(如果已经初始化) - 然后在第一次获取设备资源,也就是 GET 请求时,会依次调用
template_create_resource_attr
、template_create_addr
和template_get_handler
。 - 以后的 GET 请求只会直接调用
template_get_handler
。
总结
本文深入探讨了使用 EdgeX Foundry C-SDK 开发设备服务的几个关键点,为开发者提供了一个清晰的指导框架。通过分析设备服务的工作流、模板代码的细节以及设备增删的处理逻辑,我们可以更高效地构建自定义设备服务。
首先,设备服务的工作流强调了其与核心数据和元数据微服务的依赖性,以及通过 YAML 文件初始化配置的重要性。其次,C-SDK 的模板(template.c)提供了一个规范化的开发起点,包含必备回调函数(如 init、get、put、stop)和可选回调(如 device_added),开发者可根据需求灵活扩展。再次,删除设备的逻辑涉及内存释放回调(如 template_free_addr),而增加设备则通过 UI 或 API 触发,并涉及初始化和资源获取的回调链。
总的来说,掌握这些关键点——理解工作流、熟悉模板结构、明确设备管理的回调逻辑——能够帮助开发者快速上手 EdgeX Foundry 设备服务开发,无论是构建虚拟服务还是连接真实设备。