一、代码框架

 

 

1、新建一个4G文件,在把如图所示的4个.c文件放到工程里,加入.h文件路径

2、

2.1  cstring.c包含一些字符串操作函数

2.2  fat_core.c用于实现数据发送给模块

2.3  AXK_MD5.c 用于实现阿里的登录信息的hamcMD5算法

2.4  connet_aliyun.c就是连接阿里云的流程代码实现,包括了一机一密和一型一密。通过全局变量来切换注册方式regesit_mode

3、主函数说明,精简代码如下

int main(void)
{	


	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    
    /*继电器控制管教和指示灯管脚初始化*/
	IO_Init();
	Power_ON_init();	// 开机检测脚和电源使能脚初始化
    
	init_all();			// 变量初始?
	uart_init();	 			//串口初始化为115200	

	
	Timer2_Init(99,7199);		//定时10ms,作为南华机型粘度检测的计时基准。
	reg_fat_uart_send_byte(uart2_send_byte);


	read_stmflash();	

	SysTick_init(10);	    	 //滴答定时器10ms中断初始化	
	while(1)
	{
		
		if(HttpConnectFlag == 0)
		{
			connet_aliyun(regesit_mode);
		}
		else
		{
        }
    }
}

 

3.1    定义了定时器2,中断10ms;

3.2    reg_fat_uart_send_byte(uart2_send_byte);//注册用于和模块的通信串口,这里是串口2和模块通信,串口1用于打印日志

3.3 在while主循环中调用连接阿里云函数connet_aliyun(regesit_mode),如果连接上了,就在else语句下添加自己的要实现的发布消息和处理服务器下发的消息

4、连接阿里云流程的代码解析

void connet_aliyun(u8 mode)
{

	static int state = MD_RESET;
    int ret = 0;
	
    switch (state)
    {
		//复位模块
		case MD_RESET:
			if (module_reset())
			{
				wait_timeout(LTE_POWER_ON_WAIT_TIME);
				state = MD_AT_REQ;
			}
			break;
			
		//AT握手
		case MD_AT_REQ:
			
			if (fat_send_wait_cmdres_nonblocking("AT\r\n", 3000))//3s
			{
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					state = MD_WORK_STA_CHK;
				}
				else
				{
					if (ucErrorTimes++ > 30)
					{
						state = MD_ERR;
					}
				}
			}
			break;
			
		//模块状态检测
		case MD_WORK_STA_CHK:
			
			ret = module_is_ready();
			if (ret == MD_OK)
			{
				ucErrorTimes = 0;
				state = MD_CONNETINIT;
			}
			else if (ret == MD_ERR)
			{
				state = MD_FLIGHTMODE;
			}
			break;
			
		//连接参数初始化
		case MD_CONNETINIT:
			ret = module_connet_parm_init();
			if (ret == MD_OK)
			{
				state = MD_CONNETED;
			}
			else if (ret == MD_ERR)
			{
				state = MD_FLIGHTMODE;
			}
			break;
			
		//数据通信处理
		case MD_CONNETED:
			ret = MqttConnect();
			if( ret == MD_OK)
			{
				HttpConnectFlag = 1;
				printf("阿里云连接成功\r\n");
			}
			else if (ret == MD_ERR)
			{
				HttpConnectFlag = 0;				
				state = MD_FLIGHTMODE;			
			}
			break;
		
		//飞行模式处理
		case MD_FLIGHTMODE:
			ret = module_flightmode();
			if(ret == MD_WORK_STA_CHK)
			{
				state = MD_WORK_STA_CHK;
			}
			else if(ret == MD_ERR)
			{
				ucFlightModeTimes = 0;
				state = MD_ERR;
			}
			break;
		
		//错误
		case MD_ERR:
			ucErrorTimes = 0;
			state = MD_RESET;
			break;
	
    default:
        break;
    }

}

4.1先复位模块(stm32连接模块的电源使能脚),拉低再拉高,然后等待2S(非阻塞等待)

4.2然后发送AT指令等待应答,调用的函数fat_send_wait_cmdres_nonblocking(或者fat_send_wait_cmdres_blocking),函数原型

 * @description: 发送命令后,开启定时计数,在设置的定时时间到达后返回1,用户此时可以进行对命令的响应结果进行处理
 * @param cmd:要发送的命令
 * @param timeoutval:定时时间
 * @return 0:未到达定时时间,1:定时时间到达
 */
int fat_send_wait_cmdres_blocking(char *cmd, unsigned short int timeoutval)
{
    /* 发送命令,开启定时计数 */
    if (ucTimeOutStartFlg == 0)
    {
        FAT_DBGPRT_INFO("uart send: %s\r\n",cmd);
        fat_uart_clean();
        fat_uart_send_str((unsigned char *)cmd);
        usTimeOutVal = timeoutval / FAT_TIMER_VAL;
        ucTimeOutStartFlg = 1;
    }

    /* 到达设定的定时时间 */
    if (ucTimeOutValReachedFlg)
    {
        ucTimeOutValReachedFlg = 0;
        ucTimeOutStartFlg = 0;
        usTimeOutCount = 0;
        return 1;
    }
    return 0;
}

/**
 * @description: 发送命令后,开启定时计数,在设置的定时时间到达后或命令有响应数据时返回1,用户此时可以进行对命令的响应结果进行处理
 * @param cmd: 要发送的命令
 * @param timeoutval: 定时时间
 * @return 0:未达到定时时间,1:定时时间到达或命令有响应数据
 */
int fat_send_wait_cmdres_nonblocking(char *cmd, unsigned short int timeoutval)
{
    /* 发送命令,开启定时计数 */
    if (ucTimeOutStartFlg == 0)
    {
        FAT_DBGPRT_INFO("uart send: %s\r\n",cmd);
        fat_uart_clean();
        fat_uart_send_str((unsigned char *)cmd);
        usTimeOutVal = timeoutval / FAT_TIMER_VAL;
        ucTimeOutStartFlg = 1;
    }
    /* 到达设定的定时时间或接收到一帧数据 */
    if (ucTimeOutValReachedFlg || ucFatUartRecvFinishFlg)
    {
        ucTimeOutValReachedFlg = 0;
        ucTimeOutStartFlg = 0;
        usTimeOutCount = 0;
        return 1;
    }
    return 0;
}

2者的区别是函数说明已经写了(函数都是非阻塞的),很多别人的模块送的例程都是死循环等待,这种在实际工程中步推荐

然后调用fat_cmdres_keyword_matching("OK")去查询模块是否返回"OK"字符串,函数原型

/**
* @description: 命令响应数据中查找关键字
* @param <keyword> 要被检索的关键字
* @return 0:未检索到关键字, 1:检索到了关键字
*/
int fat_cmdres_keyword_matching(char *keyword)
{
    /* 命令有响应,在响应数据中查找关键字 */
    if (ucFatUartRecvFinishFlg)
    {
        FAT_DBGPRT_INFO("uart recv: %s\r\n",USART2_RX_BUF);
        /* 检索检索到关键词 */
        if (strstr((const char *)(USART2_RX_BUF), keyword) != NULL)
        {
            return 1;
        }
        ucFatUartRecvFinishFlg = 0;
    }
    return 0;
}

4.3 模块检测到后就是对模块进行初始化配置

int module_is_ready(void)
{
	u8 *p;
    switch (ucStateNum)
    {
		//关闭AT命令回显
		case 0x00:
			if (fat_send_wait_cmdres_blocking("ATE0\r\n", 1000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
        break;
			
		//读卡
		case 0x01:
			if (fat_send_wait_cmdres_blocking("AT+CPIN?\r\n", 1000))
			{
							//收到+CPIN: READY
				if (fat_cmdres_keyword_matching("+CPIN: READY"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{    
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;
		
		//查询信号质量
		case 0x02:
			if (fat_send_wait_cmdres_blocking("AT+CSQ\r\n", 1000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					//收到的是99(射频信号未初始化)
					if (fat_cmdres_keyword_matching("+CSQ: 99,99"))
					{
						//发送30次得不到正确应答
						if (ucErrorTimes++ > 10)
						{
								ucStateNum = MD_ERR;
						}
					}
					else
					{    
						//信号值在SIGNALMIN~SIGNALMAX这个区间
						if (match_csq((char*)USART2_RX_BUF, SIGNALMIN, SIGNALMAX))
						{
							ucErrorTimes = 0;
							ucStateNum++;
						}
						else 
						{
								ucStateNum = MD_ERR;
						}
					}
				}
							//没收到应答
				else
				{
					//发送30次不应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
        break;
		
		//查看当前GPRS附着状态
		case 0x03:
			if (fat_send_wait_cmdres_blocking("AT+CGATT?\r\n", 1000))
			{
							//收到+CGATT: 1
				if (fat_cmdres_keyword_matching("+CGATT: 1"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{    
									//发送30次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;
			
		//查看IMEI
		case 0x04:
			if (fat_send_wait_cmdres_blocking("AT+CGSN\r\n", 1000))
			{
				if (fat_cmdres_keyword_matching("OK"))
				{
					p = StrBetwString((char *)(USART2_RX_BUF),"\r\n","\r\n");	
					printf((char *)p);
					ucErrorTimes = 0;
					ucStateNum = MD_OK;
				}
				else
				{    
									//发送30次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;			
		
		//错误跳至飞行模式
		case MD_ERR:
			ucStateNum = 0;
			return MD_ERR;
		
		//完成
		case MD_OK:
				
			ucStateNum = 0;
			return MD_OK;
		default:
			break;
    }
    return 0;
}

关闭回显,检测卡是否插入,网络是否准备好,读取卡的IMEI(后面的设备名字devicename都用到),都检测成功返回OK,否则返回错误

4.4 连接阿里云

int module_connet_parm_init(void)
{
	u8 p[200];
	u16 DOWNLOAD_LEN = 0;
	static u8 md5flag = 0;
	
    switch (ucStateNum)
    {
    //关闭移动场景
		case 0x00:
			if (fat_send_wait_cmdres_blocking("AT+CIPSHUT\r\n", 1000))
			{
							//收到SHUT OK
				if (fat_cmdres_keyword_matching("SHUT OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送5次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;
			//关闭移动场景后等待2秒
			case 0x01:
					if (wait_timeout(2000))
					{
						ucStateNum++;
					}
				break;

		//设置承载类型为GPRS
		case 0x02:
			if (fat_send_wait_cmdres_blocking("AT+SAPBR=3,1,\"Contype\",\"GPRS\"\r\n", 1000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}

			break;
		//配置承载之APN 
		case 0x03:
			if (fat_send_wait_cmdres_blocking("AT+SAPBR=3,1,\"APN\",\"CMIOT\"\r\n", 1000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;
		//打开承载
		case 0x04:
			if (fat_send_wait_cmdres_blocking("AT+SAPBR=1,1\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}
			break;
			//初始化 HTTP 服务
		case 0x05:
					
			if(regesit_mode	== 0)
			{

				ucErrorTimes = 0;
				ucStateNum = 0X0D;
				
			}
			else if(regesit_mode == 1)
			{
				if(	md5flag == 0)
				{
					md5flag = 1;
					STMFLASH_Read(DeviceSecret_SAVE_ADDR,(u16*)DeviceSecret,20);  //从flash中读出DeviceSecret
					printf("xcm read DeviceSecret=%s\r\n",DeviceSecret);
					
					if(STMFLASH_ReadHalfWord(DeviceSecret_SAVE_OK)==0x88)//DeviceSecret_SAVE_OK==0x88表示设备已经获取过设备密钥,无需再次获取
					{
						ucErrorTimes = 0;
						md5flag =0;
						ucStateNum = 0X0D;
					}
				}
				else
				{
//					cat1_send_cmd("AT+HTTPINIT","OK",20);
					
					if (fat_send_wait_cmdres_nonblocking("AT+HTTPINIT\r\n", 2000))
					{
									//收到OK
						if (fat_cmdres_keyword_matching("OK"))
						{
							ucErrorTimes = 0;
							ucStateNum++;
						}
						else
						{
							//发送10次得不到正确应答
							if (ucErrorTimes++ > 10)
							{
								md5flag = 0;
								ucStateNum = MD_ERR;
							}
						}
					}					
				
				}					
			}

			break;
			
		case 0x06:
			md5flag = 0;		
			if (fat_send_wait_cmdres_nonblocking("AT+HTTPPARA=\"URL\",\"https://iot-auth.cn-shanghai.aliyuncs.com/auth/register/device\"\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;

			
		case 0x07:
					
			if (fat_send_wait_cmdres_nonblocking("AT+HTTPPARA=\"USER_DEFINED\",\"Content-Type: application/x-www-form-urlencoded\"\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;

			// 告诉HTTP服务器接下来要发送的数据长度
		case 0x08:
			if(md5flag == 0)
			{
				get_HmacMD5(1);
				md5flag = 1;
			}
			sprintf((char*)p,"productKey=%s&deviceName=%s&random=%s&sign=%s&signMethod=HmacMD5",\
				(u8*)ProductKey,(u8*)DeviceName,(u8*)random,(u8*)keyOutput);
			DOWNLOAD_LEN=strlen((char*)p);
			
			sprintf((char*)p,"AT+HTTPDATA=%d,20000\r\n",DOWNLOAD_LEN);			
			if (fat_send_wait_cmdres_nonblocking((char*)p, 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("DOWNLOAD"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 5)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;
			
			// 向HTTP服务发送数据
		case 0x09:
			md5flag = 0;
			sprintf((char*)p,"productKey=%s&deviceName=%s&random=%s&sign=%s&signMethod=HmacMD5\r\n",\
				(u8*)ProductKey,(u8*)DeviceName,(u8*)random,(u8*)keyOutput);
					
			if (fat_send_wait_cmdres_nonblocking((char*)p, 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;			

		
		case 0x0a:
					
			if (fat_send_wait_cmdres_nonblocking("AT+HTTPACTION=1\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("+HTTPACTION: 1,200"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 5)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;	

			//获取到注册数据
		case 0x0b:
					
			if (fat_send_wait_cmdres_nonblocking("AT+HTTPREAD\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("+HTTPREAD:"))
				{
					get_Registration_info();					
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 5)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;

			// 关闭http
		case 0x0c:
					
			if (fat_send_wait_cmdres_nonblocking("AT+HTTPTERM\r\n", 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 5)
					{
						ucStateNum = MD_ERR;
					}
				}
			}					
								
			break;			
			
			//MQTT链接阿里云
		case 0X0D:
			if(md5flag == 0)
			{
				get_HmacMD5(0);
				md5flag = 1;
			}
			sprintf((char*)p,"AT+MCONFIG=\"%s|securemode=3,signmethod=hmacmd5|\",\"%s&%s\",\"%s\"\r\n",\
			(u8*)DeviceName,(u8*)DeviceName,(u8*)ProductKey,keyOutput);
			
			if (fat_send_wait_cmdres_nonblocking((char*)p, 2000))
			{
							//收到OK
				if (fat_cmdres_keyword_matching("OK"))
				{				
					md5flag = 0;
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			}				

			break;
				
			// SSL链接
		case 0X0E:
			sprintf((char*)p,"AT+SSLMIPSTART=\"%s.iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n",(u8*)ProductKey);
				
			if (fat_send_wait_cmdres_blocking((char*)p, 2000))
			{
							//收到OK
				if( fat_cmdres_keyword_matching("CONNECT OK") || (fat_cmdres_keyword_matching("ALREADY")) )
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 3)
					{
						ucStateNum = MD_ERR;
					}
				}
			}				

			break;		

		case 0X0F:
				
			if (fat_send_wait_cmdres_blocking("AT+MCONNECT=1,130\r\n", 2000))
			{
							//收到OK
				if( fat_cmdres_keyword_matching("CONNACK OK") )
				{
					ucErrorTimes = 0;
					ucStateNum = MD_OK;
				}
				else
				{
					//发送10次得不到正确应答
					if (ucErrorTimes++ > 3)
					{
						ucStateNum = MD_ERR;
					}
				}
			}				

			break;			
		
		//完成
		case MD_OK:
			ucStateNum = 0;
			return MD_OK;
		
		//错误跳至飞行模式
		case MD_ERR:
			ucStateNum = 0;
			return MD_ERR;
		default:
			break;
    }
    return 0;
}

步骤00-04都是常规流程,按照上篇文章的笔记3初始化网络,然后05步判断是一机还是一型一密注册

4.4.1 一机一密

跳转到0x0d这步,调用get_HmacMD5算出用户密码,然后按照步骤执行,成功返回MD_OK

4.4.2一型一密

先判断之前是否有一型一密注册成功过,注册过则跳转到一机一密的步骤

否则,就HTTP方式获取DeviceSecret然后存在flash指定位置并置位标志,然后跳转到一机一密步骤继续执行

 

5、注册成功后,则调用注册成功回调函数MqttConnect

int MqttConnect()
{
	u8 p[500];
	u8 at_buf[4];
	switch(ucStateNum)
	{
		case 0:
			sprintf((char*)p,"AT+MSUB=\"/%s/%s/user/get\",0\r\n",(u8*)ProductKey,(u8*)DeviceName);
			if(fat_send_wait_cmdres_blocking((char*)p, 1000))
			{
				if( fat_cmdres_keyword_matching("SUBACK") )
				{
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			
			}
			break;
			
		case 1:
					ucErrorTimes = 0;
					ucStateNum++;			
			break;
		//			if(fat_send_wait_cmdres_nonblocking("AT+CIPGSMLOC=1,1\r\n",3000))//获取基站定位
//			{
//				if (fat_cmdres_keyword_matching("+CIPGSMLOC:"))
//				{
//					get_locatian();
//					

//				}
//			}
		case 2:
			if(fat_send_wait_cmdres_blocking("AT+CIPGSMLOC=1,1\r\n",3000))//获取基站定位
			{
				if (fat_cmdres_keyword_matching("+CIPGSMLOC: 0"))
				{
					get_locatian();					
					ucErrorTimes = 0;
					ucStateNum++;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			
			}
			break;
			
		case 3:
			/* 读取机器剩余清洗次数,并发送到串口屏 */		
//			AT24CXX_Read(ALLOW_CLEAN_COUNT, (u8*)at_buf, 2);
//			used_count = (at_buf[0]<<8) + at_buf[1];
//		
//			AT24CXX_Read(ALL_CLEAN_COUNT,(u8*)at_buf,2);
//			total_count = (at_buf[0]<<8) + at_buf[1];
		
			used_count = 200;
			total_count = 0;
		
			sprintf((char*)p,"AT+MPUB=\"/sys/%s/%s/thing/event/property/post\",0,0,\"{\\22id\\22:\\22123\\22,\\22version\\22:\\221.0\\22,\
				\\22params\\22:{\\22GeoLocation\\22:{\\22Longitude\\22:%s,\\22Latitude\\22:%s},\\22allcleancount\\22:%d,\\22cleanreleas\\22:%d,\\22RunningState\\22:%d},\
				\\22method\\22:\\22thing.event.property.post\\22}\"\r\n",(u8*)ProductKey,(u8*)DeviceName,Longitude,Latitude,total_count,used_count,0);//部分字符4G模块无法识别,需转义 “转义后为\\22
			if(fat_send_wait_cmdres_nonblocking((char *)p, 1000))	
			{
				if (fat_cmdres_keyword_matching("OK"))
				{				
					ucErrorTimes = 0;
					ucStateNum = MD_OK;
				}
				else
				{
									//发送10次得不到正确应答
					if (ucErrorTimes++ > 10)
					{
						ucStateNum = MD_ERR;
					}
				}
			
			}
			break;			
		
		//错误跳至飞行模式
		case MD_ERR:
			ucStateNum = 0;
			return MD_ERR;
		
		//完成
		case MD_OK:
				
			ucStateNum = 0;
			return MD_OK;
		default:
			break;	
	
	}
	return 0;

	
}

订阅主题和上传设备初始信息

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐