拓展功能

更新时间:2023-04-11 07:09:30下载pdf

除了必要的基础功能外,Wi-Fi 通用串口协议还提供了很多拓展功能,例如固件 OTA 升级、产测、时间获取等多个实用功能。

本文展示的 功能协议示例 均由模组调试助手展示。推荐您使用 涂鸦模组调试助手 协助调试,可快速了解协议实现流程。

低功耗方案

与 Wi-Fi 低功耗相关的方案总结有下面三个:

Wi-Fi 断电快连

断电快连方案是指通过给模组断电来实现低功耗的方案,适用于 Wi-Fi 模组且没法使用外电的设备,即 Wi-Fi 模组不工作时,MCU 需要控制硬件电源电路实现断开模组的供电。详细方案介绍参考 Wi-Fi 断电快连方案

拓展功能

  • 相对 Wi-Fi 通用方案,Wi-Fi 低功耗模组软件上进行了裁剪优化,缩短了断电重启时设备重新连回网络的时间。
  • Wi-Fi 低功耗模组相比 Wi-Fi 通用模组耗电更低,但峰值电流会达到 400mA 以上(持续 μs 级别),电源设计时一定要留有余量。

长连接低功耗

长连接低功耗是指设备配网后稳定没有网络控制的情况下,在保持连接状态时通过降低射频功耗来实现的低功耗,这种状态下模组的平均功耗低于 15mA

长连接低功耗使能——产品信息的 low 字段,通过添加这个字段可以打开模组这个能力。双模模组打开这个功能后,模组只有蓝牙配网功能,蓝牙控制将会关闭。例:{"p":"AIp08kLIftb8x","v":"1.0.0","m":1,"mt":10,"n":0,"ir":"5.12","low":1}

  • 0:关闭低功耗模式
  • 1:打开模组低功耗模式

Wi-Fi 在配网成功后,如果一段时间不控制(具体时间和芯片有关,一般在数秒左右),并且 IO 口没有输出(如果是照明固件,就需要关灯)模组会进入待机低功耗模式,数秒内就能观察到模组的工作电流降低,此时功耗在 0.2W 之内。

配网低功耗

配网低功耗是指配网超时机制下,模组配网超时后进入的低功耗状态,对应串口协议中设备网络状态的低功耗状态(状态6——状态值05),该状态详情见产品信息回复指令中的m字段介绍。

固件 OTA 升级

OTA(Over-the-Air)即空中下载技术,通过网络远程为设备更新和升级软件程序。

Wi-Fi 通用串口协议支持 MCU OTA 功能,通过 涂鸦 IoT 平台,先将需要更新的固件文件上传至涂鸦服务器,然后 Wi-Fi 模组通过涂鸦协议对文件进行分包传输,最后 MCU 接收升级包并写入本地闪存,最终实现固件的升级。详细的平台操作参考 固件升级选择和管理固件版本

功能流程

MCU OTA 功能需要设备 MCU 资源支持,设备配网成功后,通过平台配置或升级检测,可以启动 OTA 流程,升级流程如下:

拓展功能

Wi-Fi 模组发送完所有的升级包,重新发送查询产品指令 0x01,MCU需要在一分钟回复产品信息中的MCU软件版本号(升级后的版本号),版本号需要和在涂鸦后台配置升级的版本号保持一致。

MCU OTA 升级成功条件是固件包传输完成,设备重启上报新的版本号,两者同时完成才会提示成功。

使用场景

设备不论是在调试阶段还是出厂阶段,都可以使用 MCU OTA 功能进行 MCU 固件的更新迭代,实现设备功能的优化升级。在 MCU 硬件资源支持的情况下,建议增加 OTA 功能。

  • 固件管理:使用MCU OTA功能需要先将验证正确的MCU 固件上传到涂鸦服务器,固件上传及管理操作参考 固件管理

  • 应用说明:根据是否移植涂鸦协议 SDK分为移植SDK和自行对接,这两种方式,都需要自行完成 BootLoader 开发。

    • 移植SDK:使用MCU SDK提供的函数,回复固件分包传输大小启动升级过程,并接收模组发送的固件包,接收到的固件包需要MCU自行处理,可参考下面SDK示例介绍。
    • 自行对接:需要自行实现OTA功能相关协议指令,完成固件传输配置及固件包接收处理。

设备需要先完成协议基础功能对接,MCU RAM 需大于 260B。

指令列表

OTA 流程涉及多个协议指令:

  • 启动升级指令:0x0a
  • 升级包传输指令:0x0b

启动升级指令0x0a

启动 OTA 升级后,模组首先会使用0x0a指令告诉 MCU 升级固件包大小,此时 MCU 需回复模组固件分包传输大小。

升级包分包传输大小

回复升级包分包传输值 升级包分包大小
0x00 默认256byte(兼容旧固件)
0x01 512byte
0x02 1024byte

升级包传输指令0x0b

模组通过该指令按包传输固件包给到MCU,MCU接收到传输分包进行接收处理,若MCU 5s内未回复模组,模组将进行重发,若3次重发后仍未收到MCU回复,则认为升级失败。

指令详细介绍,请参考 Wi-Fi通用串口协议-MCU升级服务

功能协议示例

  • 启动升级指令

    拓展功能

  • 升级包传输指令
    拓展功能

MCU SDK 示例

详细的SDK移植过程参考 OTA升级

升级包分包传输大小选择函数

升级包分包传输大小选择函数upgrade_package_choose()定义在protocol.c文件中,作用是选择升级包分包传输大小。

应用步骤

  1. 打开SUPPORT_MCU_FIRM_UPDATE宏定义,开启 MCU 固件升级功能。

  2. 在串口接收数据处理函数data_handle()中,当收到模组发来的固件包大小时,MCU 调用upgrade_package_choose()回复分包大小。

    //#define         SUPPORT_MCU_FIRM_UPDATE                 //开启MCU固件升级功能(默认关闭)
    /*  Firmware package size selection  */
    #ifdef SUPPORT_MCU_FIRM_UPDATE
    #define PACKAGE_SIZE                   0        //包大小为256字节
    //#define PACKAGE_SIZE                   1        //包大小为512字节
    //#define PACKAGE_SIZE                   2        //包大小为1024字节
    #endif
    
    void data_handle(unsigned short offset)
    {
    	......
    	case UPDATE_START_CMD:                                  //启动升级指令0x0A
    			//获取升级包分包大小全局变量
    			firm_flag = PACKAGE_SIZE;
    			if(firm_flag == 0) {
    				firm_size = 256;
    			}else if(firm_flag == 1) {
    				firm_size = 512;
    			}else if(firm_flag == 2) {
    				firm_size = 1024;
    			}
    
    			firm_length = wifi_data_process_buf[offset + DATA_START];
    			firm_length <<= 8;
    			firm_length |= wifi_data_process_buf[offset + DATA_START + 1];
    			firm_length <<= 8;
    			firm_length |= wifi_data_process_buf[offset + DATA_START + 2];
    			firm_length <<= 8;
    			firm_length |= wifi_data_process_buf[offset + DATA_START + 3];//获取升级包大小
    
    			upgrade_package_choose(PACKAGE_SIZE);      //回复升级包传输分包大小
    			firm_update_flag = UPDATE_START_CMD;
    		break;
    		......
    }
    
    /**
    * @brief  升级包大小选择
    * @param[in] {package_sz} 升级包大小
    * @ref           0x00: 256byte (默认)
    * @ref           0x01: 512byte
    * @ref           0x02: 1024byte
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void upgrade_package_choose(unsigned char package_sz)
    {
    	#error "请自行实现请自行实现升级包大小选择代码,完成后请删除该行"
    	unsigned short send_len = 0;
    	send_len = set_wifi_uart_byte(send_len, package_sz);
    	wifi_uart_write_frame(UPDATE_START_CMD, MCU_TX_VER, send_len);
    }
    

升级包传输函数

升级包传输函数 mcu_firm_update_handle() 定义在 protocol.c 文件中,作用是处理接收的固件数据包。

应用步骤

  1. 启动 OTA 过程后,模组按照约定的分包大小给 MCU 发送数据包,在串口接收数据处理函数 data_handle() 中,收到模组发来的数据包。

  2. MCU 调用 mcu_firm_update_handle() 判断并做相应处理。

    void data_handle(unsigned short offset)
    {
    	......
    	case UPDATE_TRANS_CMD:                                  //升级传输
    			if(firm_update_flag == UPDATE_START_CMD) {
    				//停止一切数据上报
    				stop_update_flag = ENABLE;
    				total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    				dp_len = wifi_data_process_buf[offset + DATA_START];
    				dp_len <<= 8;
    				dp_len |= wifi_data_process_buf[offset + DATA_START + 1];
    				dp_len <<= 8;
    				dp_len |= wifi_data_process_buf[offset + DATA_START + 2];
    				dp_len <<= 8;
    				dp_len |= wifi_data_process_buf[offset + DATA_START + 3];
    
    				firmware_addr = (unsigned char *)wifi_data_process_buf;
    				firmware_addr += (offset + DATA_START + 4);
    
    				if((total_len == 4) && (dp_len == firm_length)) {
    					//最后一包
    					ret = mcu_firm_update_handle(firmware_addr,dp_len,0);
    					firm_update_flag = 0;
    				}else if((total_len - 4) <= firm_size) {
    					ret = mcu_firm_update_handle(firmware_addr,dp_len,total_len - 4);
    				}else {
    					firm_update_flag = 0;
    					ret = ERROR;
    				}
    				if(ret == SUCCESS) {
    					wifi_uart_write_frame(UPDATE_TRANS_CMD, MCU_TX_VER, 0);
    				}
    				//恢复一切数据上报
    				stop_update_flag = DISABLE;
    			}
    		break;
    	......
    	}
    
    /**
    * @brief  MCU进入固件升级模式
    * @param[in] {value} 固件缓冲区
    * @param[in] {position} 当前数据包在于固件位置
    * @param[in] {length} 当前固件包长度(固件包长度为0时,表示固件包发送完成)
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    unsigned char mcu_firm_update_handle(const unsigned char value[],unsigned long position,unsigned short length)
    {
    	#error "请自行完成MCU固件升级代码,完成后请删除该行"
    	if(length == 0) {
    		//固件数据发送完成
    	}else {
    		//固件数据处理
    	}
    	return SUCCESS;
    }
    

设备产测

Wi-Fi 通用串口协议提供了 Wi-Fi 功能性产测(分为扫描指定路由和连接指定路由)和蓝牙功能性产测功能。详细介绍参考 生产测试。除了产测功能外,Wi-Fi 通用协议还支持获取当前连接网络的信号强度。

使用场景

设备完成基础功能后,若需要对模组进行功能性测试,或者把模组产测结合到整机产测中,可使用模组的一个或多个产测功能,触发产测的方式可由 MCU 端自定义。

指令列表

设备产测功能涉及多个协议指令:

  • 扫描指定路由产测指令:0x0e
  • 连接指定路由产测指令:0x2C
  • 蓝牙功能性产测指令:0x35(子命令0x01
  • 获取信号强度指令:0x24

扫描指定路由产测指令0x0e

该指令对应的扫描产测路由产测功能,主要用于产品量产时的 Wi-Fi 模组射频性能测试,也是最常用的整机产测指令。

指令使用介绍:需等待上电初始化完成,建议至少上电5 秒以后调用该产测指令。模组接收到 MCU 发送的 0x0e 命令字后,会自动扫描名称为 tuya_mdev_test 的 Wi-Fi 信号,并返回产测结果,产测成功结果为信号强度百分比(范围为 0-100, 步进为 20)。MCU 根据信号强度判定 Wi-Fi 模组射频性能是否符合要求。

信号强度

信号强度 对应接收功率(dBm)
0 <= -100
40 > -100,<= -80
60 > -80,<= -60
80 > -60,<= -40
100 > -40
  • 路由设置:产测过程需准备一台2.4G无线路由器(可不连接外网),将该路由器SSID设置为tuya_mdev_test ,路由密码不需要关注。
  • 测试说明:建议将路由器与设备距离控制在五米左右,信号强度大于等于 60% 为合格。可以根据产线和工厂环境自行调整。可多台设备可同时进行测试。

示例:

  • MCU 发送:55 aa 03 0e 00 00 10
  • 模组返回:55 aa 00 0e 00 02 01 28 38 (产测成功,信号强度 40)

指令详细介绍,请参考 Wi-Fi通用串口协议-Wi-Fi功能性测试(扫描指定路由)

连接指定路由产测指令0x2C

该指令对应的是连接指定路由产测功能,此模式产测路由器须有联网能力,且由于路由承载能力有限,同一时间产测设备不宜过多。需要注意的是由于产测没有经过客户端 App 提供配网标志码,设备没法实际连接到涂鸦 IoT 平台,但会进行云端连接测试,产测结果更加可靠。

指令使用介绍:需等待上电初始化完成,建议至少上电5 秒以后调用该产测指令。且需要在未配网状态下才能完成测试。MCU 通过 0x2c 命令字,将产测路由的 SSID 和密码传给模组,模组连接路由器并返回云端通讯状态,MCU 根据返回的网络状态判定产测是否成功。

  • MCU 判断是否连接上路由器,根据收到 0x03 命令字的数据 (状态4-Wi-Fi已配置且连上路由器)为准。
  • 判断失败条件:
    • MCU 收到返回失败状态。
    • MCU 超过十五秒没有收到连上路由的状态包。
  • 产测成功后,可以重新发送测试命令,再次进入产测。如果没有收到连上路路由的状态包,表示模组正在产测中。需要重置模组或者重新上电后发送测试命令,才能再次进入产测。
  • 路由器名称字符串长度最大支持 32 字节,路由器密码字符串长度最大支持 64 字节

示例:

  • MCU 发送:55AA 03 2C 00 23 7B 22 73 73 69 64 22 3A 22 74 65 73 74 22 2C 22 70 61 73 73 77 6F 72 64 22 3A 22 31 32 33 34 35 36 22 7D 14({“ssid”:“test”,“password”:“123456”})
  • 模组返回:55 AA 00 2C 00 01 01 2D (产测成功)

指令详细介绍,请参考 Wi-Fi通用串口协议-Wi-Fi功能性测试(连接指定路由)

蓝牙功能性产测指令0x35(子命令0x01

蓝牙产测功能是指MCU 发起产测,模组内部扫描指定的蓝牙信标: ty_mdev,返回扫描结果和信号强度百分比。信号强度说明参照扫描指定路由产测指令。

测试说明:准备一个蓝牙信标,释放信标信号:ty_mdev。测试时建议将路由与设备距离控制在5米左右,信号强度大于等于60%为合格,也可以根据自己产线和工厂环境的情况自行调整。

示例:

  • MCU 发送:55 aa 03 35 00 01 01 {校验和}

  • 模组返回:55 aa 00 35 00 03 01 01 28 {校验和} (产测成功,信号强度 40)

指令详细介绍,请参考 Wi-Fi通用串口协议-蓝牙相关功能(可选)

获取信号强度指令0x24

模组在连接到路由网络的情况下,MCU可以发送该指令,可获取当前连接网络的信号强度,用于判定当前网络连接是否稳定。

配网设备在App的设备信息页也可以查看当前信号强度。

示例:

  • MCU 发送:55 aa 03 24 00 00 26
  • 模组返回:55 aa 00 24 00 01 D5 F9 (RSSI: -43)

指令详细介绍,请参考 Wi-Fi通用串口协议-获取当前Wi-Fi信号强度(可选)

模组返回的信号强度为 16进制(补码),如果信号强度低于-70dB,存在设备离线风险,需关注网络环境和设备天线性能。

功能协议示例

  • 扫描指定路由产测
    拓展功能
  • 连接指定路由产测
    拓展功能
  • 蓝牙功能性产测
    拓展功能

MCU SDK 示例

扫描制定路由函数

Wi-Fi 功能测试反馈函数wifi_test_result()定义在protocol.c文件中,作用是接收测试结果,并做下一步处理。

应用步骤

  1. 打开WIFI_TEST_ENABLE宏定义,开启 Wi-Fi 产测功能。

  2. 在串口接收数据处理函数data_handle()中,当收到模组发来的产测结果时,MCU 主动调用wifi_test_result()接收并做处理。

    #define         WIFI_TEST_ENABLE                //开启WIFI产测功能(扫描指定路由)
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef WIFI_TEST_ENABLE
    		case WIFI_TEST_CMD:                              //wifi功能测试(扫描指定路由指令)
    			result = wifi_data_process_buf[offset + DATA_START];
    			rssi = wifi_data_process_buf[offset + DATA_START + 1];
    			wifi_test_result(result, rssi);
    		break;
    	#endif
    	......
    }
    
    /**
    * @brief  wifi功能测试反馈
    * @param[in] {result} wifi功能测试结果
    * @ref       0: 失败
    * @ref       1: 成功
    * @param[in] {rssi} 测试成功表示wifi信号强度/测试失败表示错误类型
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void wifi_test_result(unsigned char result,unsigned char rssi)
    {
    	#error "请自行实现wifi功能测试成功/失败代码,完成后请删除该行"
    	if(result == 0) {
    		//测试失败
    		if(rssi == 0x00) {
    			//未扫描到名称为tuya_mdev_test路由器,请检查
    		}else if(rssi == 0x01) {
    			//模组未授权
    		}
    	}else {
    		//测试成功
    		//rssi为信号强度(0-100, 0信号最差,100信号最强)
    	}
    }
    

连接指定路由产测函数

连接指定路由产测函数mcu_start_connect_wifitest()定义在mcu_api.c文件中,作用是 MCU 上报指定路由名称及密码,发起连接指定路由产测。

应用步骤

  1. 打开WIFI_CONNECT_TEST_ENABLE宏定义,开启连接指定路由产测功能。

  2. MCU 自行调用mcu_start_connect_wifitest()函数,上报测试连接的路由名称及密码,打开产测功能。

  3. 在串口接收数据处理函数data_handle()中,当收到模组发来的产测结果时,MCU 主动调用wifi_connect_test_result()接收测试结果并做处理。

    //#define         WIFI_CONNECT_TEST_ENABLE                //开启WIFI产测功能(连接指定路由)
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef WIFI_CONNECT_TEST_ENABLE
    		case WIFI_CONNECT_TEST_CMD:               //wifi功能测试(连接指定路由)
    			result = wifi_data_process_buf[offset + DATA_START];
    			wifi_connect_test_result(result);
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  mcu发起wifi功能测试(连接指定路由)
    * @param[in] {ssid_buf} 存放路由器名称字符串数据的地址(ssid长度最大支持32个字节)
    * @param[in] {passwd_buffer} 存放路由器名称字符串数据的地址(passwd长度最大支持64个字节)
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void mcu_start_connect_wifitest(unsigned char *ssid_buf,unsigned char *passwd_buffer)
    {
    	unsigned short send_len = 0;
    
    	if( my_strlen(ssid_buf) > 32 || my_strlen(passwd_buffer) > 64) {
    		//printf("ssid_buf or passwd_buffer is too long!");
    		return;
    	}
    
    	send_len = set_wifi_uart_buffer(send_len, "{\"ssid\":\"", my_strlen("{\"ssid\":\""));
    	send_len = set_wifi_uart_buffer(send_len,ssid_buf,my_strlen(ssid_buf));
    	send_len = set_wifi_uart_buffer(send_len, "\",\"password\":\"", my_strlen("\",\"password\":\""));
    	send_len = set_wifi_uart_buffer(send_len,passwd_buffer,my_strlen(passwd_buffer));
    	send_len = set_wifi_uart_buffer(send_len, "\"}", my_strlen("\"}"));
    
    	wifi_uart_write_frame(WIFI_CONNECT_TEST_CMD, MCU_TX_VER, send_len);
    }
    
    /**
    * @brief  路由信息接收结果通知
    * @param[in] {result} 模块是否成功接收到正确的路由信息
    * @ref       0x00: 失败
    * @ref       0x01: 成功
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void wifi_connect_test_result(unsigned char result)
    {
    	#error "请自行实现wifi功能测试成功/失败代码,完成后请删除该行"
    	if(result == 0) {
    		//路由信息接收失败,请检查发出的路由信息包是否是完整的JSON数据包
    	}else {
    		//路由信息接收成功,产测结果请注意WIFI_STATE_CMD指令的wifi工作状态
    	}
    }
    

蓝牙产测函数

蓝牙产测函数mcu_start_BLE_test()定义在mcu_api.c文件中,作用是 MCU 发起蓝牙功能性测试。

应用步骤

  1. 打开BLE_RELATED_FUNCTION_ENABLE宏定义,开启蓝牙相关功能。

  2. MCU 自行调用mcu_start_BLE_test()函数,打开扫描指定蓝牙信标产测功能。

  3. 在串口接收数据处理函数data_handle()中,当收到模组发来的产测结果时,MCU 主动调用BLE_test_result()接收测试结果并做处理。

    //#define         BLE_RELATED_FUNCTION_ENABLE            //开启蓝牙相关功能
    
    /**
    * @brief  mcu发起蓝牙功能性测试(扫描指定蓝牙信标)
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void mcu_start_BLE_test(void)
    {
    	unsigned short send_len = 0;
    	send_len = set_wifi_uart_byte(send_len, 0x01);
    	wifi_uart_write_frame(BLE_TEST_CMD, MCU_TX_VER, send_len);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef BLE_RELATED_FUNCTION_ENABLE
    		case BLE_TEST_CMD:                             //蓝牙功能性测试(扫描指定蓝牙信标)
    			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    			BLE_test_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  蓝牙功能性测试结果
    * @param[in] {value} 数据缓冲区
    * @param[in] {length} 数据长度
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void BLE_test_result(const unsigned char value[], unsigned short length)
    {
    	#error "请自行实现蓝牙功能性测试结果代码,完成后请删除该行"
    	unsigned char sub_cmd = value[0];
    
    	if(0x03 != length) {
    		//数据长度错误
    		return;
    	}
    	if(0x01 != sub_cmd) {
    		//子命令错误
    		return;
    	}
    	unsigned char result = value[1];
    	unsigned char rssi = value[2];
    	if(result == 0) {
    		//测试失败
    		if(rssi == 0x00) {
    			//未扫描到名称为 ty_mdev蓝牙信标,请检查
    		}else if(rssi == 0x01) {
    			//模组未授权
    		}
    	}else if(result == 0x01) {
    		//测试成功
    		//rssi为信号强度(0-100, 0信号最差,100信号最强)
    	}
    }
    

时间同步

支持 MCU 获取格林时间和本地时间,设备在连接网络后,MCU可以通过指令获取当前的系统时间。

时间说明:MCU 拿到的时间是模组的时间,模组在入网后会通过云端校时,模块在网期间每次http交互时会与云端校时,无交互时设备也会6h定期到云端校时一次。模组自身带有RTC,在模组离线期间,MCU拿到的时间是模组自身RTC的时间。

时间服务通知说明:指模组上电重新入网后时间与云端校准后主动通知MCU,可以选择格林时间或本地时间。模组在连接上服务器之后时间戳并不会马上校准,有个时间周期导致每次上电都要 MCU 不断的重试去获取时间,这个服务开启后,模组在时间校准之后会主动通知 MCU。

模组RTC 24小时内时间误差小于10s。

使用场景

若设备需要做系统时间显示,或者设备功能需要用到时间,都可以启用时间获取功能,并实时校准。

为保证初次获取时间数据准确,需在模块入网后5s获取,此后获取时间校准间隔可依据使用场景决定,建议不要太过频繁,间隔时间至少大于1秒。

指令列表

时间同步功能涉及多个协议指令:

  • 获取格林时间指令:0x0C
  • 获取本地时间指令:0x1C
  • 打开时间服务通知指令:0x34(子命令0x01)
  • 模组时间服务通知指令:0x34(子命令0x02)

获取格林时间指令0x0C

格林时间是不带有时区和夏令时的因素,是一个国际标准的时间基准,MCU 可主动向模组获取格林时间。

当模组连接上网络后,本地的时间戳校准完成才会返回成功,并携带有效的时间数据。

示例:

  • MCU 发送:55 aa 03 0c 00 00 0e

  • 模组返回:55 aa 00 0c 00 07 01 10 04 13 05 06 07 4c(格林时间2016年4月19日5时6分7秒)

指令详细介绍,请参考 Wi-Fi通用串口协议-获取系统时间(格林时间)

获取本地时间指令0x1C

本地时间是在格林时间的基础上加上当地(设备激活所在地)时区和夏令时的时间。

当地时间,是指配网时手机的系统时区:

  • 如设备在国内配网激活使用,则当地时间为北京时间(手机的系统时区/东8区)。

  • 如设备在国外配网激活使用,则当地时间为设备所处时区时间(手机的系统时区)。

示例:

  • MCU 发送:55 aa 03 1C 00 00 1E

  • 模组返回:55 aa 00 1c 00 08 01 10 04 13 05 06 07 02 5f(北京时间2016年4月19日5时6分7秒)

指令详细介绍,请参考 Wi-Fi通用串口协议-获取本地时间

打开时间服务通知指令0x34(子命令0x01)

指令使用:上电后MCU发送打开时间服务通知指令,并选择时间服务,模组收到后开启时间服务通知,并告知MCU功能开启结果。

模组不重新上电的情况下服务开启后不接受重复开启,模组不重启的情况下需要获取时间走时间相关获取协议。

示例:

  • MCU 发送:55 AA 03 34 00 02 01 00 39(选择格林时间)
  • 模组返回:55 AA 00 34 00 02 01 00 36(服务开启成功)

模组时间服务通知指令0x34(子命令0x02)

指令使用:模组时间与云端校准后,模组根据 MCU 发送的打开时间通知的服务,选择发送相对应的时间数据给到MCU

模组重新上电,服务都是关闭的,都需要 MCU 重新发送打开模组时间通知服务。

示例:

  • 模组发送:55 AA 00 34 00 09 02 00 15 06 02 03 05 11 03 77(Type: 0(格林时间), Time: 2021/06/02 03:05:17 星期三)

  • MCU 返回:55 AA 03 34 00 01 02 39

指令详细介绍,请参考 Wi-Fi通用串口协议-模组拓展服务

功能协议示例

  • 获取格林时间
    拓展功能
  • 获取本地时间
    拓展功能
  • 打开模组时间服务通知
    拓展功能
  • 模组时间通知
    拓展功能

MCU SDK 示例

获取格林时间函数

获取格林时间函数mcu_get_green_time()定义在mcu_api.c文件中,作用是 MCU 主动获取格林时间。

应用步骤

  1. 打开SUPPORT_GREEN_TIME宏定义,开启格林时间功能。

  2. MCU 主动调用mcu_get_green_time()函数,发送格林时间获取指令。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的获取结果后,调用mcu_get_greentime()函数接收判断,并做下一步处理。

    //#define         SUPPORT_GREEN_TIME                //开启格林时间功能
    
    /**
    * @brief  MCU获取格林时间
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void mcu_get_green_time(void)
    {
    	wifi_uart_write_frame(GET_ONLINE_TIME_CMD, MCU_TX_VER, 0);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef SUPPORT_GREEN_TIME
    		case GET_ONLINE_TIME_CMD:                               //获取格林时间
    			mcu_get_greentime((unsigned char *)(wifi_data_process_buf + offset + DATA_START));
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  获取到的格林时间
    * @param[in] {time} 获取到的格林时间数据
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void mcu_get_greentime(unsigned char time[])
    {
    	#error "请自行完成相关代码,并删除该行"
    	/*
    	time[0] 为是否获取时间成功标志,为 0 表示失败,为 1表示成功
    	time[1] 为年份,0x00 表示 2000 年
    	time[2] 为月份,从 1 开始到12 结束
    	time[3] 为日期,从 1 开始到31 结束
    	time[4] 为时钟,从 0 开始到23 结束
    	time[5] 为分钟,从 0 开始到59 结束
    	time[6] 为秒钟,从 0 开始到59 结束
    	*/
    	if(time[0] == 1) {
    		//正确接收到wifi模组返回的格林数据
    
    	}else {
    		//获取格林时间出错,有可能是当前wifi模组未联网
    	}
    }
    

获取本地时间函数

获取本地时间函数mcu_get_system_time()定义在mcu_api.c文件中,作用是 MCU 主动获取本地时间。

应用步骤

  1. 打开SUPPORT_MCU_RTC_CHECK宏定义,开启本地时间功能。

  2. MCU 主动调用mcu_get_system_time()函数,发送本地时间获取指令。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的获取结果后,调用mcu_write_rtctime()函数接收判断,并做下一步处理。

    //#define         SUPPORT_MCU_RTC_CHECK                //开启校时功能
    
    /**
    * @brief  MCU获取系统时间,用于校对本地时钟
    * @param  Null
    * @return Null
    * @note   MCU主动调用完成后在mcu_write_rtctime函数内校对rtc时钟
    */
    void mcu_get_system_time(void)
    {
    	wifi_uart_write_frame(GET_LOCAL_TIME_CMD, MCU_TX_VER, 0);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef SUPPORT_MCU_RTC_CHECK
    		case GET_LOCAL_TIME_CMD:               //获取本地时间
    			mcu_write_rtctime((unsigned char *)(wifi_data_process_buf + offset + DATA_START));
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  MCU校对本地RTC时钟
    * @param[in] {time} 获取到的格林时间数据
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void mcu_write_rtctime(unsigned char time[])
    {
    	#error "请自行完成RTC时钟写入代码,并删除该行"
    	/*
    	Time[0] 为是否获取时间成功标志,为 0 表示失败,为 1表示成功
    	Time[1] 为年份,0x00 表示 2000 年
    	Time[2] 为月份,从 1 开始到12 结束
    	Time[3] 为日期,从 1 开始到31 结束
    	Time[4] 为时钟,从 0 开始到23 结束
    	Time[5] 为分钟,从 0 开始到59 结束
    	Time[6] 为秒钟,从 0 开始到59 结束
    	Time[7] 为星期,从 1 开始到 7 结束,1代表星期一
    */
    	if(time[0] == 1) {
    		//正确接收到wifi模组返回的本地时钟数据
    
    	}else {
    		//获取本地时钟数据出错,有可能是当前wifi模组未联网
    	}
    }
    

打开时间服务通知函数

打开时间服务通知函数open_module_time_serve()定义在mcu_api.c文件中,作用是 MCU 打开模组时间服务通知。

应用步骤

  1. 打开MODULE_EXPANDING_SERVICE_ENABLE宏定义,开启模组拓展服务功能。

  2. MCU 主动调用open_module_time_serve()函数,发送打开模组时间服务通知指令,并选择服务时间类型。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的获取结果后,调用模组拓展功能函数open_module_time_serve_result()接收判断,并做下一步处理。

    //#define         MODULE_EXPANDING_SERVICE_ENABLE        //开启模组拓展服务功能
    
    /**
    * @brief  打开模块时间服务通知
    * @param[in] {time_type} 时间类型
    * @ref       0x00: 格林时间
    * @ref       0x01: 本地时间
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void open_module_time_serve(unsigned char time_type)
    {
    	unsigned short send_len = 0;
    	send_len = set_wifi_uart_byte(send_len, 0x01);
    	send_len = set_wifi_uart_byte(send_len, time_type);
    	wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef MODULE_EXPANDING_SERVICE_ENABLE
    		case MODULE_EXTEND_FUN_CMD:                             //模组拓展服务
    			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    			open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  打开模块时间服务通知结果
    * @param[in] {value} 数据缓冲区
    * @param[in] {length} 数据长度
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void open_module_time_serve_result(const unsigned char value[], unsigned short length)
    {
    	......
    		case 0x01: { //子命令  打开模组时间服务通知
    			if(0x02 != length) {
    				//数据长度错误
    				return;
    			}
    
    			if(value[1] == 0) {
    				//服务开启成功
    			}else {
    				//服务开启失败
    			}
    		}
    		break;
    		......
    }
    

模组时间服务通知函数

模组时间服务通知在模组拓展功能函数open_module_time_serve_result()中,收到模组发来的时间后,自行添加代码做下一步处理。

//#define         MODULE_EXPANDING_SERVICE_ENABLE        //开启模组拓展服务功能
void data_handle(unsigned short offset)
{
	......
	#ifdef MODULE_EXPANDING_SERVICE_ENABLE
		case MODULE_EXTEND_FUN_CMD:                             //模组拓展服务
			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
			open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
		break;
	#endif
	......
	}
/**
* @brief  打开模块时间服务通知结果
* @param[in] {value} 数据缓冲区
* @param[in] {length} 数据长度
* @return Null
* @note   MCU需要自行实现该功能
*/
void open_module_time_serve_result(const unsigned char value[], unsigned short length)
{
	......
	case 0x02: {  //子命令  模组时间服务通知
			if(0x09 != length) {
				//数据长度错误
				return;
			}
			unsigned char time_type = value[1]; //0x00:格林时间  0x01:本地时间
			unsigned char time_data[7];
			my_memcpy(time_data, value + 2, length - 2);
			/*
			Data[0]为年份, 0x00表示2000年
			Data[1]为月份,从1开始到12结束
			Data[2]为日期,从1开始到31结束
			Data[3]为时钟,从0开始到23结束
			Data[4]为分钟,从0开始到59结束
			Data[5]为秒钟,从0开始到15结束
			Data[6]为星期,从1开始到7结束,1代表星期一
			*/
			//在此处添加时间数据处理代码,time_type为时间类型
			unsigned short send_len = 0;
			send_len = set_wifi_uart_byte(send_len,sub_cmd);
			wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
		}
		break;
		......
}

天气数据

模组支持获取天气数据,详见 天气预报服务功能

使用场景

模组连接到云端后,MCU 可通过发送指令启用天气获取功能,开启成功后模组会定时将天气数据下发到 MCU。

天气数据的地区是基于配网手机所在的经纬度。

指令列表

天气数据功能涉及多个协议指令:

  • 打开获取天气数据功能指令:0x20
  • 下发天气数据指令:0x21
  • 主动获取天气指令:0x34(子命令0x03

打开获取天气数据功能指令0x20

指令使用:设备完成初始化后就可以调用该指令开启天气数据功能,模组收到后返回功能开启结果。
示例:

  • MCU 发送:55 AA 03 20 00 0E 06 77 2E 74 65 6D 70 06 77 2E 70 6D 32 35 80(L:0x06 K:w.temp。L:0x06 K:w.pm25)

  • 模组返回:55 AA 00 20 00 02 01 00 22 (成功)

指令详细介绍,请参考 Wi-Fi通用串口协议-打开获取天气数据功能(可选)

下发天气数据指令0x21

该指令为下发天气数据指令,在打开天气数据功能后模组定时下发,前提是设备连接到云端。开启获取天气功能后会立马下发一次,后续以30分钟的间隔下发。主动获取天气时也是调用0x21指令下发天气数据。

示例: w.temp: 15, w.humidity: 23, w.pm25: 27, w.conditionNum: 120(对应天气状况为晴,查询中文天气UTF-8编码表可知)

天气服务 编码16进制 天气数据 编码16进制
w.temp 77 2E 74 65 6D 70 15 00 00 00 0F
w.humidity 77 2E 68 75 6D 69 64 69 74 79 23 00 00 00 17
w.pm25 77 2E 70 6D 32 35 27 00 00 00 1B
w.conditionNum 77 2E 63 6F 6E 64 69 74 69 6F 6E 4E 75 6D 120 31 32 30
  • 模组发送:55 AA 00 21 00 40 01 06 77 2E 74 65 6D 70 00 04 00 00 00 0F 0A 77 2E 68 75 6D 69 64 69 74 79 00 04 00 00 00 17 06 77 2E 70 6D 32 35 00 04 00 00 00 1B 0E 77 2E 63 6F 6E 64 69 74 69 6F 6E 4E 75 6D 01 03 31 32 30 5B
  • MCU 返回:55 aa 00 21 00 00 20

指令详细介绍,请参考 Wi-Fi通用串口协议-下发天气数据(可选)

主动获取天气指令0x34(子命令0x03

针对有些产品需求,需要在半个小时主动发送的天气服务基础上,拥有主动获取天气服务数据的能力。提供这个命令用于用户主动获取天气服务接口数据。

  • 该指令的使用频率不能小于一分钟,一分钟内的多次请求只处理一次。
  • 该指令用于确认数据请求,数据下发还是通过0x21的下发天气数据的命令。

指令详细介绍,请参考 Wi-Fi通用串口协议-模组拓展服务

功能协议示例

  • 打开获取天气数据功能和下发天气数据
    拓展功能
  • 主动获取天气数据
    拓展功能

MCU SDK 示例

打开获取天气数据功能函数

打开获取天气数据功能函数mcu_open_weather()定义在protocol.c文件中,作用是 MCU 主动发送打开获取天气数据功能指令,打开天气服务。

应用步骤

  1. 打开WEATHER_ENABLE宏定义,开启天气功能,并配置天气服务数量及天气预报天数。

  2. MCU 自行调用mcu_open_weather()函数打开天气服务。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的打开结果后,调用打开天气功能返回用户自处理函数weather_open_return_handle()接收判断,并做下一步处理。

    //#define         WEATHER_ENABLE                  //打开天气功能
    #ifdef          WEATHER_ENABLE
    /*  在protocol.c文件中weather_choose数组中可调整,然后将打开服务的类型数目写到此宏定义  */
    #define         WEATHER_CHOOSE_CNT              4   //选择的需要天气服务类型的数目
    /*  在打开天气服务时,可以设置此宏定义选择天气预报的天数,1表示当天天气(不需要预报可设置为1),最多为7天(不可以设置成0或大于7)  */
    #define         WEATHER_FORECAST_DAYS_NUM       1   //设置天气预报的天数
    #endif
    
    /**
    * @brief  mcu打开天气服务
    * @param  Null
    * @return Null
    */
    void mcu_open_weather(void)
    {
    	int i = 0;
    	char buffer[13] = {0};
    	unsigned char weather_len = 0;
    	unsigned short send_len = 0;
    
    	weather_len = sizeof(weather_choose) / sizeof(weather_choose[0]);
    
    	for(i=0;i<weather_len;i++) {
    		buffer[0] = sprintf(buffer+1,"w.%s",weather_choose[i]);
    		send_len = set_wifi_uart_buffer(send_len, (unsigned char *)buffer, buffer[0]+1);
    	}
    
    	#error "请根据提示,自行完善打开天气服务代码,完成后请删除该行"
    	/*
    	//当获取的参数有和时间有关的参数时(如:日出日落),需要搭配t.unix或者t.local使用,需要获取的参数数据是按照格林时间还是本地时间
    	buffer[0] = sprintf(buffer+1,"t.unix"); //格林时间   或使用  buffer[0] = sprintf(buffer+1,"t.local"); //本地时间
    	send_len = set_wifi_uart_buffer(send_len, (unsigned char *)buffer, buffer[0]+1);
    	*/
    
    	buffer[0] = sprintf(buffer+1,"w.date.%d",WEATHER_FORECAST_DAYS_NUM);
    	send_len = set_wifi_uart_buffer(send_len, (unsigned char *)buffer, buffer[0]+1);
    
    	wifi_uart_write_frame(WEATHER_OPEN_CMD, MCU_TX_VER, send_len);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	case WEATHER_OPEN_CMD:                                  //打开天气服务返回
    			weather_open_return_handle(wifi_data_process_buf[offset + DATA_START], wifi_data_process_buf[offset + DATA_START + 1]);
    		break;
    	......
    	}
    
    /**
    * @brief  打开天气功能返回用户自处理函数
    * @param[in] {res} 打开天气功能返回结果
    * @ref       0: 失败
    * @ref       1: 成功
    * @param[in] {err} 错误码
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void weather_open_return_handle(unsigned char res, unsigned char err)
    {
    	#error "请自行完成打开天气功能返回数据处理代码,完成后请删除该行"
    	unsigned char err_num = 0;
    
    	if(res == 1) {
    		//打开天气返回成功
    	}else if(res == 0) {
    		//打开天气返回失败
    		//获取错误码
    		err_num = err;
    	}
    }
    
    #ifdef WEATHER_ENABLE
    			if(wifi_work_state == WIFI_CONNECTED && isWoSend == 0) { //当WIFI连接成功,打开天气数据且仅一次
    				mcu_open_weather();
    				isWoSend = 1;
    			}
    #endif
    

下发天气数据函数

天气数据解析函数weather_data_raw_handle()定义在system.c文件中,作用是接收模组发来天气数据。

应用步骤

  1. 在串口接收数据处理函数data_handle()中,收到模组发来的天气数据。

  2. 调用天气数据解析函数weather_data_raw_handle()接收判断,并做下一步处理。

    weather_data_user_handle()函数是用户自处理天气数据函数,自行实现,下列代码仅为示例。

    void data_handle(unsigned short offset)
    {
    	......
    	case WEATHER_DATA_CMD:                                  //天气数据下发
    			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    			weather_data_raw_handle((unsigned char *)wifi_data_process_buf + offset + DATA_START, total_len);
    		break;
    	......
    	}
    
    /**
    * @brief  天气数据解析
    * @param[in] {p_data} 接收数据指针
    * @param[in] {data_len} 接收数据长度
    * @return Null
    */
    static void weather_data_raw_handle(const unsigned char p_data[], unsigned short data_len)
    {
    	int i = 1;
    	int can_len = 0;
    	char can[15] = {0};
    	char day = 0;
    	int type1 = 0;
    	unsigned char value_string[100] = {0};
    	int val_cnt = 0;
    	int val_len = 0;
    
    	if(p_data[0] != 1 || data_len < 1) {
    		//接收失败
    	}else {
    		if(data_len < 4) {
    			//数据为空
    		}
    
    		while (i < data_len) {
    			can_len = p_data[i];
    
    			my_memset(can, '\0', 15);
    			my_memcpy(can, p_data + i + 1, can_len - 2);
    
    			day = p_data[i + can_len] - '0';
    
    			type1 = p_data[i + 1 + can_len];
    			if(type1 != 0 && type1 != 1) {
    				return;
    			}
    
    			my_memset(value_string, '\0', 100);
    			val_cnt = i + 1 + can_len + 1;
    			val_len = p_data[val_cnt];
    			if (type1 == 0) { //int32
    				weather_data_user_handle(can+2, type1, p_data+val_cnt+1, day);
    			}
    			else if(type1 == 1) { //string
    				my_memcpy(value_string, p_data + val_cnt + 1, val_len);
    				weather_data_user_handle(can+2, type1, value_string, day);
    			}
    
    			i += 1 + can_len + 1 + 1 + val_len;
    		}
    
    		wifi_uart_write_frame(WEATHER_DATA_CMD, 0, 0);
    	}
    }
    
    /**
    * @brief  天气数据用户自处理函数
    * @param[in] {name} 参数名
    * @param[in] {type} 参数类型
    * @ref       0: int 型
    * @ref       1: string 型
    * @param[in] {data} 参数值的地址
    * @param[in] {day} 哪一天的天气  0:表示当天 取值范围: 0~6
    * @ref       0: 今天
    * @ref       1: 明天
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void weather_data_user_handle(char *name, unsigned char type, const unsigned char *data, char day)
    {
    	#error "这里仅给出示例,请自行完善天气数据处理代码,完成后请删除该行"
    	int value_int;
    	char value_string[50];//由于有的参数内容较多,这里默认为50。您可以根据定义的参数,可以适当减少该值
    
    	my_memset(value_string, '\0', 50);
    
    	//首先获取数据类型
    	if(type == 0) { //参数是INT型
    		value_int = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
    	}else if(type == 1) {
    		my_strcpy(value_string, data);
    	}
    
    	//注意要根据所选参数类型来获得参数值!!!
    	if(my_strcmp(name, "temp") == 0) {
    		printf("day:%d temp value is:%d\r\n", day, value_int);          //int 型
    	}else if(my_strcmp(name, "humidity") == 0) {
    		printf("day:%d humidity value is:%d\r\n", day, value_int);      //int 型
    	}else if(my_strcmp(name, "pm25") == 0) {
    		printf("day:%d pm25 value is:%d\r\n", day, value_int);          //int 型
    	}else if(my_strcmp(name, "condition") == 0) {
    		printf("day:%d condition value is:%s\r\n", day, value_string);  //string 型
    	}
    }
    

主动获取天气函数

主动获取天气函数request_weather_serve()定义在mcu_api.c文件中,作用是 MCU 发送主动获取天气功能指令,主动请求天气服务数据。

应用步骤

  1. 打开MODULE_EXPANDING_SERVICE_ENABLE宏定义,开启模组拓展服务功能。

  2. MCU 主动调用request_weather_serve()函数,发送主动获取天气功能指令请求天气服务数据。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的回复结果后,调用模组拓展功能函数open_module_time_serve_result()接收判断,并做下一步处理。

    //#define         MODULE_EXPANDING_SERVICE_ENABLE        //开启模组拓展服务功能
    
    /**
    * @brief  主动请求天气服务数据
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void request_weather_serve(void)
    {
    	unsigned short send_len = 0;
    	send_len = set_wifi_uart_byte(send_len, 0x03);
    	wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef MODULE_EXPANDING_SERVICE_ENABLE
    		case MODULE_EXTEND_FUN_CMD:                             //模组拓展服务
    			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    			open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  打开模块时间服务通知结果
    * @param[in] {value} 数据缓冲区
    * @param[in] {length} 数据长度
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void open_module_time_serve_result(const unsigned char value[], unsigned short length)
    {
    	......
    	case 0x03: {  //子命令  主动请求天气服务数据
    			if(0x02 != length) {
    				//数据长度错误
    				return;
    			}
    
    			if(value[1] == 0) {
    				//成功
    			}else {
    				//失败
    			}
    		}
    		break;
    		......
    }
    

关闭心跳

MCU 主动给模组发送通知 Wi-Fi 模组关闭心跳指令,关闭 Wi-Fi 模组的心跳发送。

使用场景

对于需要休眠降低功耗的 MCU 模组,可在休眠前发送该指令关闭Wi-Fi模组心跳,方便进入休眠状态。

指令列表

通知Wi-Fi模组关闭心跳0x25

  • 该指令请勿在设备刚上电时发送,Wi-Fi 模组上电后需要和 MCU 建立心跳连接
  • 关闭心跳指令重启后不保存,即如果希望模组重新上电后也关闭心跳,需要建立心跳后重新发送关闭指令。

指令详细介绍,请参考 Wi-Fi通用串口协议-通知Wi-Fi模组关闭心跳

功能协议示例

拓展功能

MCU SDK 示例

关闭心跳指令函数

关闭心跳包检测函数wifi_heart_stop()定义在 SDK 的mcu_api.c文件中,作用是发送关闭心跳包指令,关闭心跳。

应用步骤

  1. 先打开WIFI_HEARTSTOP_ENABLE宏定义,开启心跳停止功能。

  2. 在需要关闭心跳的时刻调用wifi_heart_stop()

    /******************************************************************************
    					8:是否开启WIFI模组心跳关闭功能
    如需要请开启该宏,调用mcu_api.c文件内wifi_heart_stop函数即可停止心跳
    ******************************************************************************/
    //#define         WIFI_HEARTSTOP_ENABLE           //开启心跳停止功能
    
    /**
    * @brief  通知WIFI模组关闭心跳
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void wifi_heart_stop(void)
    {
    	wifi_uart_write_frame(HEAT_BEAT_STOP, MCU_TX_VER, 0);
    }
    

查询联网状态

MCU 发送该指令可主动获取 Wi-Fi 模组的联网状态

使用场景

报告设备联网状态指令只有模组检测到 MCU 重启或 MCU断线再上线的过程,才会主动下发Wi-Fi 联网状态给到MCU ,如果 MCU 需要主动获取 Wi-Fi 模组的联网状态,可通过发送获取Wi-Fi 联网状态指令请求模组发送当前联网状态到MCU。

指令列表

获取Wi-Fi 联网状态指令0x2B

0x03指令只有在模组状态变化时,才会主动发送模组的网络状态给 MCU ,而 MCU 也可以主动向模组查询当前模组的网络状态

主动获取联网状态指令需要等待设备初始化完成才可调用,建议在收到模组0x03指令下发过联网状态后才可以使用0x2B指令获取,或者在初始化完成后延时5~10秒获取。

指令详细介绍,请参考 Wi-Fi通用串口协议-获取当前 Wi-Fi 联网状态

功能协议示例

拓展功能

MCU SDK 示例

主动获取 Wi-Fi 状态函数

主动获取 Wi-Fi 网络状态函数mcu_get_wifi_connect_status()定义在mcu_api.c文件中,作用是主动请求 Wi-Fi 状态。

应用步骤

  1. 主动获取 Wi-Fi 网络状态的功能可以通过启动GET_WIFI_STATUS_ENABLE的宏定义打开。

  2. 打开后 MCU 调用mcu_get_wifi_connect_status()函数,向模组发送0x2B指令,获取当前 Wi-Fi 模组状态。

  3. 在串口数据处理函数data_handle()中,当收到模组发来的网络状态result时,MCU 可自行调用get_wifi_status()函数根据网络状态做产品逻辑处理。

    //#define         GET_WIFI_STATUS_ENABLE                  //开启获取当前WIFI联网状态功能
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef GET_WIFI_STATUS_ENABLE
    				case GET_WIFI_STATUS_CMD:                        //获取当前wifi联网状态
    					result = wifi_data_process_buf[offset + DATA_START];
    					get_wifi_status(result);
    				break;
    		#endif
    		......
    		}
    
    #ifdef GET_WIFI_STATUS_ENABLE
    /**
    * @brief  获取当前wifi联网状态
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void mcu_get_wifi_connect_status(void)
    {
    	wifi_uart_write_frame(GET_WIFI_STATUS_CMD, MCU_TX_VER, 0);
    }
    #endif
    

设备重置通知

模组支持本地移除、App 移除、App 恢复出厂设置,但 MCU 不知道模组这些状态的通知,这个功能用于有需要的用户打开模组状态通知。

使用场景

MCU获取模组重置状态通知

指令列表

设备重置通知功能涉及多个协议指令:

  • 打开模组重置状态通知指令:0x34(子命令0x04
  • 模组重置状态通知指令:0x34(子命令0x05

打开模组重置状态通知指令0x34(子命令0x04

该指令的作用是打开模组重置状态通知

示例:

  • MCU 发送:55 aa 03 34 00 01 04 3B
  • 模组返回:55 aa 00 34 00 02 04 00 39 (设置成功)

指令详细介绍,请参考 Wi-Fi通用串口协议-模组拓展服务

该指令断电后不保存,即每次上电后需要重新调用才有效

模组重置状态通知指令0x34(子命令0x05

该指令的作用是发送模组重置状态通知给到MCU

示例:

  • 模组发送:55 aa 00 34 00 02 05 02 3C(APP恢复出厂重置))

  • MCU 返回:55 aa 03 34 00 01 05 3C (设置成功)

指令详细介绍,请参考 Wi-Fi通用串口协议-模组拓展服务

重置状态的发送最多也会重发两次,重发间隔保持1s。

功能协议示例

拓展功能

MCU SDK 示例

模组重置状态通知函数

模组重置状态通知函数open_module_reset_state_serve()定义在mcu_api.c文件中,作用是MCU打开模组重置状态通知。

应用步骤

  1. 打开MODULE_EXPANDING_SERVICE_ENABLE宏定义,开启模组拓展服务功能。

  2. MCU主动调用open_module_reset_state_serve()函数,发送打开模组重置状态通知指令。

  3. 在串口接收数据处理函数data_handle()中,收到模组发来的获取结果后,调用模组功能拓展函数open_module_time_serve_result()接收判断,并做下一步处理。

    //#define         MODULE_EXPANDING_SERVICE_ENABLE        //开启模组拓展服务功能
    
    /**
    * @brief  打开模块重置状态通知
    * @param  Null
    * @return Null
    * @note   MCU需要自行调用该功能
    */
    void open_module_reset_state_serve(void)
    {
    	unsigned short send_len = 0;
    	send_len = set_wifi_uart_byte(send_len, 0x04);
    	wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
    }
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef MODULE_EXPANDING_SERVICE_ENABLE
    		case MODULE_EXTEND_FUN_CMD:                             //模组拓展服务
    			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
    			open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
    		break;
    	#endif
    	......
    	}
    
    /**
    * @brief  打开模块时间服务通知结果
    * @param[in] {value} 数据缓冲区
    * @param[in] {length} 数据长度
    * @return Null
    * @note   MCU需要自行实现该功能
    */
    void open_module_time_serve_result(const unsigned char value[], unsigned short length)
    {
    	......
    	case 0x04: {  //子命令  打开模组重置状态通知
    			if(0x02 != length) {
    				//数据长度错误
    				return;
    			}
    
    			if(value[1] == 0) {
    				//成功
    			}else {
    				//失败
    			}
    		}
    		break;
    }
    

模组重置状态通知函数

模组重置状态通知在模组功能拓展函数open_module_time_serve_result()中,收到模组发来的重置状态通知后,自行添加代码做下一步处理。

//#define         MODULE_EXPANDING_SERVICE_ENABLE        //开启模组拓展服务功能
void data_handle(unsigned short offset)
{
	......
	#ifdef MODULE_EXPANDING_SERVICE_ENABLE
		case MODULE_EXTEND_FUN_CMD:                             //模组拓展服务
			total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
			open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
		break;
	#endif
		......
	}
/**
* @brief  打开模块时间服务通知结果
* @param[in] {value} 数据缓冲区
* @param[in] {length} 数据长度
* @return Null
* @note   MCU需要自行实现该功能
*/
void open_module_time_serve_result(const unsigned char value[], unsigned short length)
{
	......
	case 0x05: {  //子命令  模组重置状态通知
			if(0x02 != length) {
				//数据长度错误
				return;
			}
			switch(value[1]) {
				case 0x00:
					//模组本地重置
				break;
				case 0x01:
					//APP远程重置
				break;
				case 0x02:
					//APP恢复出厂重置
				break;
				default:break;
			}
			unsigned short send_len = 0;
			send_len = set_wifi_uart_byte(send_len, sub_cmd);
			wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
		}
		break;
		......
}

同步上报

除了异步上报指令0x03外,模组还提供同步上报指令0x22。同步上报功能与异步上报功能类似,不同点就是上报使用的是同步指令,每次上报数据后,都会收到模组的应答结果,告知MCU上报是否成功。

使用场景

MCU需要数据上报的场景都可以使用同步上报功能,由于同步上报功能较异步上报占用模组资源多,建议使用异步上报指令完成MCU 数据上报功能,不过下列情况可以使用同步上报功能:

  • 验证 MCU 上报数据是否成功,可以使用同步上报指令观察模组应答结果
  • 通过同步上报指令上报设备状态,上报数据不会被模组过滤

指令列表

同步上报指令0x22

该指令的作用是完成同步上报功能。上报格式与异步上报指令0x07相同,不同的是0x22为同步上报指令,每次发送模组都会有响应,未响应前不可多次上报,且同步上报连续相同的DP数据模组端不做过滤。

指令详细介绍,请参考 Wi-Fi通用串口协议-状态上报(同步)

网络不好,数据难以及时上报时,模组会在5秒后返回失败,MCU需要等待大于5秒。

功能协议示例

拓展功能

MCU SDK 示例

同步上报函数

同步上报函数根据dp数据类型分为:mcu_dp_raw_update_syn()mcu_dp_bool_update_syn()mcu_dp_value_update_syn()mcu_dp_string_update_syn()mcu_dp_enum_update_syn()mcu_dp_fault_update_syn(),这些函数定义在mcu_api.c文件中,作用是同步上报dp状态。

应用步骤

  1. 如果需要使用同步上报功能,打开MCU_DP_UPLOAD_SYN宏定义。

  2. MCU主动调用同步上报函数上报dp状态。

  3. 在串口接收数据处理函数data_handle()中,当收到模组发来的上报回复时,调用get_upload_syn_result()函数判断同步上报结果,并根据结果做处理,如上报失败可以重新发送。

    //#define         MCU_DP_UPLOAD_SYN                   //开启同步状态上报功能
    
    void data_handle(unsigned short offset)
    {
    	......
    	#ifdef MCU_DP_UPLOAD_SYN
    		case STATE_UPLOAD_SYN_RECV_CMD:                         //状态上报(同步)
    			result = wifi_data_process_buf[offset + DATA_START];
    			get_upload_syn_result(result);
    		break;
    		#endif
    		......
    		}
    
    /**
    * @brief  raw型dp数据同步上传
    * @param[in] {dpid} dpid号
    * @param[in] {value} 当前dp值指针
    * @param[in] {len} 数据长度
    * @return Null
    * @note   Null
    */
    unsigned char mcu_dp_raw_update_syn(unsigned char dpid,const unsigned char value[],unsigned short len)
    {
    	unsigned short send_len = 0;
    
    	if(stop_update_flag == ENABLE)
    		return SUCCESS;
    	//
    	send_len = set_wifi_uart_byte(send_len,dpid);
    	send_len = set_wifi_uart_byte(send_len,DP_TYPE_RAW);
    	//
    	send_len = set_wifi_uart_byte(send_len,len / 0x100);
    	send_len = set_wifi_uart_byte(send_len,len % 0x100);
    	//
    	send_len = set_wifi_uart_buffer(send_len,(unsigned char *)value,len);
    
    	wifi_uart_write_frame(STATE_UPLOAD_SYN_CMD,MCU_TX_VER,send_len);
    
    	return SUCCESS;
    }
    
    void get_upload_syn_result(unsigned char result)
    {
    	#error "请自行完成状态同步上报结果代码,并删除该行"
    
    	if(result == 0) {
    		//同步上报出错
    	}else {
    		//同步上报成功
    	}
    }
    

红外能力

红外能力是一项附加功能,能够在原有的产品上增加万能红外遥控器的基本功能,拥有红外能力。

文件传输

文件传输功能分为文件下载功能和文件上传功能,文件下载功能已支持,上传功能补充中。文件下载功能介绍参考串口协议

扫地机地图数据服务

扫地机地图流数据传输功能是针对扫地机地图数据传输的服务,详细功能介绍及应用参考串口协议

射频功能

通用固件提供了射频功能,详细功能介绍及应用参考串口协议-射频功能

文件下载服务

通用固件提供了文件下载服务,详细功能介绍及应用参考串口协议-文件下载服务

蓝牙遥控器功能

通用固件提供了蓝牙遥控器功能,详细功能介绍及应用参考串口协议-蓝牙遥控器功能

风扇类产品服务

通用固件提供了风扇类产品服务,详细功能介绍及应用参考串口协议-风扇类产品服务