当使用STM32 ARM Cortex-M微控制器时,ST的免费嵌入式软件STM32Cube提供了所有必要的驱动程序和中间件组件,以减少初始的开发工作。在上述提到的中间件组件中,其中一个是非常受欢迎的FreeRTOS实时操作系统,Nabto正在努力建立一个强大的FreeRTOS + Nabto组合的解决方案。
我们最新推出AppMyProduct应用平台可帮助您快速开发远程控制设备的高质量应用程序。本文介绍了在STM32F746G-DISCO开发板上使用Nabto + FreeRTOS的演示热泵应用,该应用程序可由我们的Heat Control Ionic启动器应用程序控制。
你需要些什么 ● STM32F746G-DISCO开发板 ● USB和以太网电缆 该演示在STM32F746G-DISCO开发板上进行了测试,但应该可以移植到类似的STM32开发板上。
为什么选择Nabto和它如何工作? 你有没有想过从本地网络外部连接到您的STM32设备,不需要使用破坏路由器和防火墙配置或缓慢而不透明的云服务?在您的STM32设备上运行uNabto服务器,您可以使用静态设备ID建立一个快速安全的对等连接,无论在任何地方,都可以使用静态设备ID。
那么Nabto如何做到这一点?下图进行了简要概述。您的STM32开发板代表了运行uNabto服务器的设备。一旦它连接到互联网,它将在Nabto Basestation中使用其唯一的设备ID来标识自身。如果客户端(例如我们的Heat Control离子启动应用程序)想要连接到STM32开发板,则将具有ID的连接请求发送到基站,然后就会建立与设备的直接连接。
Nabto在STM32Cube架构的位置 如前所述,STM32Cube提供了一个硬件抽象层API和一些中间件组件。我们要在STM32Cube中间件之上实现构建的uNabto服务器,如下图所示:
uNabto服务器本身分为两层: ● 实际的uNabto框架(uNabto SDK) ● uNabto平台适配器,在uNabto框架和STM32Cube中间件之间的抽象层 因此,我们只需要实现uNabto平台适配器,以便将uNabto服务器和演示应用程序移植到STM32平台。
实现平台适配器 平台适配器作为通用uNabto框架和STM32Cube中间件层之间的链接,包括将用于网络的LwIP TCP / IP堆栈。 LCD日志实用程序用于在屏幕上显示Nabto日志输出。
适配器分为单个文件,如Nabto文档(TEN023 Nabto设备SDK指南第12章)中所述: ● unabto_config.h:基本的uNabto配置 ● unabto_platform_types.h:定义所有必需的uNabto类型 ● unabto_platform.h:平台特定的ad-hoc功能 ● network_adapter.c:初始化、关闭、读取和写入网络数据的功能 ● time_adapter.c:时间函数 ● dns_adapter.c:DNS解析 ● random_adapter.c:随机生成器 ● log_adapter.c:日志 如果您对如何实现详细的平台适配器感兴趣,请查看GitHub上演示版本的Inc和Src目录中的适配器文件。
实现Nabto线程 创建平台适配器后,uNabto服务器就可以使用了。 初始化uNabto,并运行在它自己的FreeRTOS线程中。线程在Src / unabto_main.c中定义: - static void unabto_thread()
- {
- const char* device_id = "<DEVICE ID>";
- const char* pre_shared_key = "<KEY>";
-
- // Init uNabto
- nabto_main_setup* nms = unabto_init_context();
- nms->id = strdup(device_id);
-
- nms->secureAttach = true;
- nms->secureData = true;
- nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
-
- if (!unabto_read_psk_from_hex(pre_shared_key, nms->presharedKey, 16)) {
- NABTO_LOG_ERROR(("Invalid cryptographic key specified", pre_shared_key));
- return;
- }
-
- if (!unabto_init()) {
- NABTO_LOG_FATAL(("Failed at nabto_main_init"));
- }
-
- // Init demo application
- demo_init(do_factory_reset);
- demo_application_set_device_name("STM32F746G-DISCO");
- demo_application_set_device_product("ACME 9002 Heatpump");
- demo_application_set_device_icon_("img/chip-small.png");
-
- // Main loop
- for (;;) {
- unabto_tick();
- osDelay(10);
- demo_application_tick();
- }
- }
复制代码
以上代码使用您唯一的设备ID和portal.appmyproduct.com中的预共享加密密钥初始化服务器。然后初始化热泵演示,稍后将简要描述。最后,无限循环重复地调用unabto_tick()方法。这将触发框架来检查新的UDP数据包并发送响应。时钟滴答之间的时间应该是大约10毫秒,这是通过硬操作系统延迟和一些额外的演示特定工作负载来实现的。
要启动Nabto线程,我们提供一个unabto_start()方法。初始化TCP / IP协议栈后,由主程序调用,并从DHCP服务器设置静态IP地址或获取动态IP地址。 - void unabto_start()
- {
- sys_thread_new("uNabto", unabto_thread, NULL, DEFAULT_THREAD_STACKSIZE, NABTO_THREAD_PRIO);
- }
复制代码
接收的客户端请求的实际处理在application_event()回调函数中实现。处理程序使用与客户端共享的接口定义。 - application_event_result application_event(application_request* request,
- unabto_query_request* query_request,
- unabto_query_response* query_response) {
-
- NABTO_LOG_INFO(("Nabto application_event: %u", request->queryId));
- debug_dump_acl();
-
- // handle requests as defined in interface definition shared with
- // client - for the default demo, see
- // https://github.com/nabto/ionic-starter-nabto/blob/master/www/nabto/unabto_queries.xml
-
- application_event_result res;
-
- switch (request->queryId) {
- case 10000:
- // get_public_device_info.json
- if (!write_string(query_response, device_name_)) return AER_REQ_RSP_TOO_LARGE;
- if (!write_string(query_response, device_product_)) return AER_REQ_RSP_TOO_LARGE;
- if (!write_string(query_response, device_icon_)) return AER_REQ_RSP_TOO_LARGE;
- if (!unabto_query_write_uint8(query_response, fp_acl_is_pair_allowed(request))) return AER_REQ_RSP_TOO_LARGE;
- if (!unabto_query_write_uint8(query_response, fp_acl_is_user_paired(request))) return AER_REQ_RSP_TOO_LARGE;
- if (!unabto_query_write_uint8(query_response, fp_acl_is_user_owner(request))) return AER_REQ_RSP_TOO_LARGE;
- return AER_REQ_RESPONSE_READY;
-
- case 10010:
- // set_device_info.json
- if (!fp_acl_is_request_allowed(request, REQUIRES_OWNER)) return AER_REQ_NO_ACCESS;
- res = copy_string(query_request, device_name_, sizeof(device_name_));
- if (res != AER_REQ_RESPONSE_READY) return res;
- if (!write_string(query_response, device_name_)) return AER_REQ_RSP_TOO_LARGE;
- return AER_REQ_RESPONSE_READY;
-
- case 11000:
- // get_users.json
- return fp_acl_ae_users_get(request, query_request, query_response); // implied admin priv check
-
- case 11010:
- // pair_with_device.json
- if (!fp_acl_is_pair_allowed(request)) return AER_REQ_NO_ACCESS;
- res = fp_acl_ae_pair_with_device(request, query_request, query_response);
- debug_dump_acl();
- return res;
-
- // [...]
- }
- }
复制代码
有关热泵演示应用的更多详细信息,请查看Src / unabto_application.c中的源代码。
上手操作! 上述的理论足够了。我们来试试演示!该演示程序是一个System Workbench for STM32(SW4STM32)工程,可以在GitHub获得。只需按照README中的说明进行操作即可。
开发板应该会在液晶显示屏上打印出Nabto日志,如文章开头的图片所示。
现在,使用Heat Control Ionic启动器应用程序连接到您的设备,并根据您的应用输入查看LCD显示屏底部的参数。模拟室温缓慢收敛到目标温度。您可以通过按下刷新按钮更新应用程序中的当前室温。
设备设置永久存储在STM32闪存中。如果要执行“出厂复位”,请在启动/复位期间按电路板上的User按钮。您应该会看到FACTORY RESET打印到显示屏上。
译者注:本文译自:https://blog.nabto.com/2017/03/2 ... ertos-appmyproduct/,感谢CHRISTIAN做出的贡献。如有错漏,敬请指正。
|