2017年5月23日星期二

在STM32F746G-DISCO开发板上使用Nabto + FreeRTOS的演示热泵应用

当使用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中定义:
  1. static void unabto_thread()
  2. {
  3.   const char* device_id = "<DEVICE ID>";
  4.   const char* pre_shared_key = "<KEY>";

  5.   // Init uNabto
  6.   nabto_main_setup* nms = unabto_init_context();
  7.   nms->id = strdup(device_id);

  8.   nms->secureAttach = true;
  9.   nms->secureData = true;
  10.   nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;

  11.   if (!unabto_read_psk_from_hex(pre_shared_key, nms->presharedKey, 16)) {
  12.     NABTO_LOG_ERROR(("Invalid cryptographic key specified", pre_shared_key));
  13.     return;
  14.   }

  15.   if (!unabto_init()) {
  16.     NABTO_LOG_FATAL(("Failed at nabto_main_init"));
  17.   }

  18.   // Init demo application
  19.   demo_init(do_factory_reset);
  20.   demo_application_set_device_name("STM32F746G-DISCO");
  21.   demo_application_set_device_product("ACME 9002 Heatpump");
  22.   demo_application_set_device_icon_("img/chip-small.png");

  23.   // Main loop
  24.   for (;;) {
  25.     unabto_tick();
  26.     osDelay(10);
  27.     demo_application_tick();
  28.   }
  29. }
复制代码

以上代码使用您唯一的设备ID和portal.appmyproduct.com中的预共享加密密钥初始化服务器。然后初始化热泵演示,稍后将简要描述。最后,无限循环重复地调用unabto_tick()方法。这将触发框架来检查新的UDP数据包并发送响应。时钟滴答之间的时间应该是大约10毫秒,这是通过硬操作系统延迟和一些额外的演示特定工作负载来实现的。

要启动Nabto线程,我们提供一个unabto_start()方法。初始化TCP / IP协议栈后,由主程序调用,并从DHCP服务器设置静态IP地址或获取动态IP地址。
  1. void unabto_start()
  2. {
  3.   sys_thread_new("uNabto", unabto_thread, NULL, DEFAULT_THREAD_STACKSIZE, NABTO_THREAD_PRIO);
  4. }
复制代码

接收的客户端请求的实际处理在application_event()回调函数中实现。处理程序使用与客户端共享的接口定义。
  1. application_event_result application_event(application_request* request,
  2.                                            unabto_query_request* query_request,
  3.                                            unabto_query_response* query_response) {

  4.     NABTO_LOG_INFO(("Nabto application_event: %u", request->queryId));
  5.     debug_dump_acl();

  6.     // handle requests as defined in interface definition shared with
  7.     // client - for the default demo, see
  8.     // https://github.com/nabto/ionic-starter-nabto/blob/master/www/nabto/unabto_queries.xml

  9.     application_event_result res;

  10.     switch (request->queryId) {
  11.     case 10000:
  12.         // get_public_device_info.json
  13.         if (!write_string(query_response, device_name_)) return AER_REQ_RSP_TOO_LARGE;
  14.         if (!write_string(query_response, device_product_)) return AER_REQ_RSP_TOO_LARGE;
  15.         if (!write_string(query_response, device_icon_)) return AER_REQ_RSP_TOO_LARGE;
  16.         if (!unabto_query_write_uint8(query_response, fp_acl_is_pair_allowed(request))) return AER_REQ_RSP_TOO_LARGE;
  17.         if (!unabto_query_write_uint8(query_response, fp_acl_is_user_paired(request))) return AER_REQ_RSP_TOO_LARGE;
  18.         if (!unabto_query_write_uint8(query_response, fp_acl_is_user_owner(request))) return AER_REQ_RSP_TOO_LARGE;
  19.         return AER_REQ_RESPONSE_READY;

  20.     case 10010:
  21.         // set_device_info.json
  22.         if (!fp_acl_is_request_allowed(request, REQUIRES_OWNER)) return AER_REQ_NO_ACCESS;
  23.         res = copy_string(query_request, device_name_, sizeof(device_name_));
  24.         if (res != AER_REQ_RESPONSE_READY) return res;
  25.         if (!write_string(query_response, device_name_)) return AER_REQ_RSP_TOO_LARGE;
  26.         return AER_REQ_RESPONSE_READY;

  27.     case 11000:
  28.         // get_users.json
  29.         return fp_acl_ae_users_get(request, query_request, query_response); // implied admin priv check

  30.     case 11010:
  31.         // pair_with_device.json
  32.         if (!fp_acl_is_pair_allowed(request)) return AER_REQ_NO_ACCESS;
  33.         res = fp_acl_ae_pair_with_device(request, query_request, query_response);
  34.         debug_dump_acl();
  35.         return res;

  36.         // [...]
  37.     }
  38. }
复制代码

有关热泵演示应用的更多详细信息,请查看Src / unabto_application.c中的源代码。

上手操作!
上述的理论足够了。我们来试试演示!该演示程序是一个System Workbench for STM32(SW4STM32)工程,可以在GitHub获得。只需按照README中的说明进行操作即可。

开发板应该会在液晶显示屏上打印出Nabto日志,如文章开头的图片所示。

现在,使用Heat Control Ionic启动器应用程序连接到您的设备,并根据您的应用输入查看LCD显示屏底部的参数。模拟室温缓慢收敛到目标温度。您可以通过按下刷新按钮更新应用程序中的当前室温。

设备设置永久存储在STM32闪存中。如果要执行“出厂复位”,请在启动/复位期间按电路板上的User按钮。您应该会看到FACTORY RESET打印到显示屏上。

没有评论:

发表评论