快速接入阿里云物联网平台技术方案分享

随着物联网设备的普及,物联网操作系统也成了广大开发者热烈讨论的话题之一,很多的组织和厂商都推出了在物联网节点上的基础软件——物联网操作系统,如国内云服务供应商Alibaba推出的AliOS Things ,Amazon公司的Amazon FreeRTOS,再如开源社区领袖Linux基金会推出的Zephyr,以及在国内知名度很高的RT-Thread等等。

今天我们来对AliOS Things中的示例linkkitapp例程进行一下解析,希望可以为你解惑一二。

系统架构

AliOS Things是什么?

AliOS Things是面向IoT领域的轻量级物联网嵌入式操作系统。致力于搭建云端一体化IoT基础设备。具备极致性能,极简开发、云端一体、丰富组件、安全防护等关键能力,并支持终端设备连接到阿里云Link,可广泛应用在智能家居、智慧城市、新出行等领域。

AliOS Things是阿里巴巴推出的物联网设备端软件框架,物联网设备可以通过AliOS Things设备框架接入阿里云,使用云服务器提供的相关物联网设备服务。

AliOS Things软件框架是基于APACHE2.0协议的开源软件,项目地址为:https://github.com/alibaba/AliOS-Things

AliOS Things软件架构可以从下到上分为四层,硬件和硬件抽象层、AOS操作系统层、应用框架层和应用层,下层组件为上层业务逻辑的实现提供支撑机制。

从底部到顶部,AliOS Things包括:

  • 板级支持包(BSP):主要由SoC供应商开发和维护
  • 硬件抽象层(HAL):比如WiFi和UART
  • 内核:包括Rhino实时操作系统内核、Yloop, VFS, KV 存储
  • 协议栈:包括TCP/IP协议栈(LwIP),uMesh网络协议栈
  • 安全:安全传输层协议(TLS),可信服务框架(TFS)、可信运行环境(TEE)
  • AOS API:提供可供应用软件和中间件使用的API
  • 中间件:包括常见的物联网组件和阿里巴巴增值服务中间件
  • 示例应用:阿里自主开发的示例代码,以及通过了完备测试的应用程序(比如Alinkapp) 所有的模组都已经被组织成组件,且每个组件都有自己的.mk文件,用于描述它和其它组件间的依赖关系,方便应用开发者按需选用。

我们一般只需要关心示例应用部分,找一个跟自己的需求接近的示例,然后在其上进行更改即可,我们使用的示例就是linkkitapp。

结构框图

目录结构

为什么D5(GPIO14)是一键配网的引脚?

首先我们看一下,D5引脚在哪里?

官方介绍: WeMos D1 mini pins and diagram

https://escapequotes.net/esp8266-wemos-d1-mini-pins-and-diagram/

D5是WeMos D1 mini模块的引脚,GPIO14是ESP8266的引脚,两个标识对应的一个引脚。

那linkkitapp代码中哪里对应着一键配网的代码呢?

程序入口在app_entry.c中的int application_start(int argc, char ** argv) 函数。

在application_start函数中有这样一行:

从函数名上看,这是一个注册事件过滤器的,过滤的目标是按键点击事件,并处理按键点击事件的,“linkkit按键处理”回调函数。

该函数的实现如下:

事件值为VALUE_KEY_CLICK将进入awss配网模式;

事件值为VALUE_KEY_LTCLICK将进行awss复位操作。

经过定位排查,我们知道在 key_poll_func(void * arg) 函数中,实现了判断按键(短按、长按、长长按),然后分别向系统发出不同的按键事件aos_post_event()。

由上我们知道了AliOS定义的配网按键就是GPIO14,也就是mini D1 ESP8266模块的D5脚。。

详细请参考:ESP8266配网--key.c之按键事件分析https://www.jianshu.com/p/fab0ea9e9ad3

ESP8266与主单片机之间的关系

STM32-->ESP8266-->阿里云物联网平台-->手机等终端

我们使用ESP8266模块,只是把ESP8266当做一个数据传输的媒介,STM32与ESP8266模块通过串口进行通信。

STM32获得外部传感器的状态,然后通过串口发送状态至ESP8266模块。

经ESP8266模块内部的AliOS Things对数据包进行打包,然后将数据包通过WiFi网络发送至阿里云物联网平台。

由于手机端与阿里云物联网平台保持着长连接,所以阿里云物联网平台获得到的传感器数据能够及时推送至手机端,进而保持设备端的传感器数据和手机端的数据保持一致性。

手机等终端-->阿里云物联网平台-->ESP8266-->STM32

反过来,通过手机端的云智能APP对设备进行操作,首先会将操作设备的指令推送至阿里云物联网平台,阿里云物联网平台会及时将指令推送至ESP8266模块,ESP8266模块会对收到的指令进行数据转发,将指令通过串口传输给STM32。

由于阿里云物联网平台推荐数据格式为ICA标准数据格式(Alink JSON),STM32端需要对接收到的串口信息进行解析,即对接收到的JSON字符串进行解析,然后对解析后的结果进行判断,根据指令不同进而做不同的动作。

有人可能会说,ESP8266这个单片机性能这么好,不利用它浪费了;

还有人会说对于智能风扇这样的简单应用,只需要ESP8266作为主芯片即可,加上外围电路,多省事多节约成本呀。

的确ESP8266性能很好,只是使用ESP8266的确够用。那我们为什么还要使用上面这种方式,额外浪费一个STM32单片机呢?

这种方式最大的好处就是,降低物联网模块的使用门槛,为什么这么说呢?

上面的通信方式,只需要一个具有串口功能的单片机就可以与ESP8266配合使用,而一般的单片机都有1-2个以上的串口,所以条件很容易就满足了。

这样,我们只需要在你原有的设计方案的基础上,额外占用一个串口,就可以在不改变整体电路设计的基础上,添加物联网功能。

而外围单片机的选择就很自由了,可以根据功能需要,选择便宜的或者性能比ESP8266更优的作为主单片机。

另外一点,如果拿ESP8266作为主单片机的话,那么就要对ESP8266有比较深入的了解,这样无疑增大了难度,当某天需求改变或者ESP8266性能无法满足的时候,我们更换了ESP8266的芯片,那么整体方案都要改,而且你还要重新熟悉一个新的物联网芯片,学习成本太高了。

需要解决的问题

ESP8266 有两个UART:UART0和UART1。

UART0有TX、RX,可以作为系统的打印信息输出接口和数据收发口。

UART1的RX被Flash占用,只有发送引脚TX(GPIO2,即UART1_TXD)可供使用,所以一般作为打印信息输出接口(调试用)。

通常情况下,我们使用UART0和外设通讯,而使用UART1作为日志打印端口。

D1 mini ESP8266模块两个串口的所在位置:

我们使用一个Micro USB线与D1 mini ESP8266模块相连,使用串口会收到如下打印信息:

我们可以看到默认的linkkitapp示例,Log信息是通过UART0发送出来的,而且里面有很多咱们不关心的信息,应该将此部分信息进行屏蔽。

所以我们需要做如下几个工作:

  1. 将串口的比特率由921600修改为115200(此部分工作可不做);
  2. 交换UART0和UART1,让UART1输出Log日志;UART0与STM32进行通信;
  3. 将STM32发上来的信息,通过UART0接收并发送到云端;将云端下发的有用的信息通过UART0转发给STM32。

解决问题1. 串口的初始化api在platform\mcu\esp8266\bsp\driver\uart.c 中,目前的代码是默认如果不设置,uart0波特率是921600。但是一旦初始化了uart1,uart0的波特率会被改为和uart1一样。

void
uart_init_new(uart_dev_t *uart)
{
    UART_WaitTxFifoEmpty(UART0);
    UART_WaitTxFifoEmpty(UART1);

    if (uart == NULL)
    {
        return;
    }


    if (uart->port == 1)
    {
        //printf("port= 1\n ");

        //uart1 setting
        UART_ConfigTypeDef uart_config;
        uart_config.baud_rate = uart->config.baud_rate;
        uart_config.data_bits = UART_WordLength_8b;
        uart_config.parity = USART_Parity_None;
        uart_config.stop_bits = USART_StopBits_1;
        uart_config.flow_ctrl = USART_HardwareFlowControl_None;
        uart_config.UART_RxFlowThresh = 120;
        uart_config.UART_InverseMask = UART_None_Inverse;
        //UART_ParamConfig(UART0, &uart_config);


        //uart2 setting for log
        //uart_config.baud_rate = uart->config.baud_rate;
        UART_ParamConfig(UART1, &uart_config);

        UART_SetPrintPort(UART1);
        //UART_intr_handler_register(uart0_rx_isr, NULL);
        ETS_UART_INTR_ENABLE();
    }
    else
    {
        //printf("port= 0 \n ");
        UART_ConfigTypeDef uart_config;
        uart_config.baud_rate = uart->config.baud_rate;
        // uart_config.baud_rate = BIT_RATE_921600;
        uart_config.data_bits = UART_WordLength_8b;
        uart_config.parity = USART_Parity_None;
        uart_config.stop_bits = USART_StopBits_1;
        uart_config.flow_ctrl = USART_HardwareFlowControl_None;
        uart_config.UART_RxFlowThresh = 120;
        uart_config.UART_InverseMask = UART_None_Inverse;
        UART_ParamConfig(UART0, &uart_config);


        UART_IntrConfTypeDef uart_intr;
        uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
        uart_intr.UART_RX_FifoFullIntrThresh = 100;//10
        uart_intr.UART_RX_TimeOutIntrThresh = 10;//2
        uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
        UART_IntrConfig(UART0, &uart_intr);


        UART_SetPrintPort(UART0);
        UART_intr_handler_register(uart0_rx_isr, NULL);
        ETS_UART_INTR_ENABLE();
    }
}

解决问题2. 交换UART0和UART1:修改此文件:AliOS-Things\platform\mcu\esp8266\hal\uart.c

解决问题3.

  • 下发有用信息:

  • 上发有用信息:

模拟上传属性

经过上面的改造之后,我们只需要向UART0发送JSON格式的数据,即可修改服务器端的数值,比如串口助手中发送:

{"CurrentTemperature":26}

发送完毕,服务器端的当前温度值将会修改为26℃,在运行状态中可以实时看出来当前温度值是实时变化的。

模拟设置属性

手机端APP点击某个按钮之后,将会将数据包发送至ESP8266,ESP8266将有用信息通过UART0的TX引脚发送给STM32,STM32将收到服务器端指令,对此指令进行解析,进而做相应的动作,具体逻辑类似下图所示。

调试真实设备中,对电源开关设置为1,即{"PowerSwitch":1},在串口助手中我们收到指令{"PowerSwitch":1};

我们对电源开关设置为0,即{"PowerSwitch":0},可以看到串口助手中,收到对应的指令{"PowerSwitch":0}。

STM32中我们使用cJSON对上面字符串进行解析即可,然后做相应的动作,即完成了云端对设备的远程控制。

细心的人可能发现了,为什么我们用CurrentTemperature或者PowerSwitch来设置属性呢?其实他们就是我们创建产品的时候,进行功能定义的时候,设置的标识符。

到此为止,本月的“智能风扇”涉及到的知识点基本都已经讲过了,下一篇网文,就对此项目进行最后的收尾,大家敬请期待哈。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 2
收藏 4
关注 64
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧