阿里云一型一密免预注册——单片机C语言实现

阿里云一型一密免预注册——单片机C语言实现

一型一密

一型一密两种使用方式:
● 一型一密预注册:
设备联网前,需要在物联网平台预注册设备DeviceName,建议采用设备的MAC地址、IMEI、SN码等作为DeviceName。物联网平台为设备颁发DeviceSecret。
云端鉴权成功后,设备采用设备证书(ProductKey、DeviceName和DeviceSecret)与云端建立通信连接。
支持通过MQTT通道、HTTP通道进行一型一密预注册认证。
● 一型一密免预注册:
不需要在物联网平台预注册设备DeviceName,便于使用物联网卡卡号等作为DeviceName。
云端鉴权成功后,设备采用ProductKey、ProductSecret、ClientID和DeviceToken与云端建立通信连接。
支持通过MQTT通道进行一型一密预注册认证。

一型一密免预注册

此处记录免预注册几个要点:

  1. 建立TLS通道 ,TCP通道不行。
  2. 免预注册仅支持MQTT方式,不支持HTTP方式。
  3. 注册方式 与MQTT普通连接方法相同 ,只是连接请求中包含的元素不同。
  4. instanceId,实例ID,阿里云手册说在物联网平台控制台实例管理页面查看,实际上公共实例没有ID,这个参数就不需要。如果公共实例,却填了该参数,connect时会收到回复04错误,看起来像是用户名或密码不对,实际上是这个参数错误。
  5. 注册连接成功后,服务器会自动回复参数
  6. 然后可以主动断开连接,也可以等15s自动断开连接

代码

此处贴三个函数,一个是注册参数初始化与连接,一个是正常参数初始化连接,还有连接函数。
其中,连接函数中固定报头不一定是2字节,实际上得看可变报头+有效负荷的长度,在一部分自编的连接函数案例中,都是固定的2字节。

//创建TLS通道,然后发起MQTT注册连接
void ali_register_connect(void)
{
    
    
	char content[128] = {
    
    0};
	sprintf(content,"deviceName%sproductKey%srandom123",device_name,product_key);

	char mqttPassword[64] = {
    
    0};
	utils_hmac_sha1((const char*)content,strlen((const char*)content),(char *)mqttPassword,product_secret,product_secret_len);
	
	char mqttClientId[128] = {
    
    0};
	sprintf((char *)mqttClientId,"%s|securemode=-2,authType=regnwl,random=123,signmethod=hmacsha1|",device_name);

	char mqttUserName[64]={
    
    0};
	sprintf((char *)mqttUserName,"%s&%s",device_name,product_key);
	mqtt_connect((char *)mqttClientId,(char *)mqttUserName,(char *)mqttPassword);
	//此处可延时,然后获取回复后进行解析
	......
}
// 建立TCP连接,然后使用注册时返回的clientid和devicetoken,发起MQTT连接
int ali_normal_connect(void)
{
    
    
	char clientID[64]={
    
    0};
	char deviceToken[64]={
    
    0};
	STMFLASH_Read(ALI_CLIENTID_ADDR,(uint16_t *)clientID,32);
	STMFLASH_Read(ALI_DEVICETOKEN_ADDR,(uint16_t *)deviceToken,32);
	
	strcat(clientID,"|securemode=-2,authType=connwl|");
	char mqttUserName[64]={
    
    0};
	sprintf((char *)mqttUserName,"%s&%s",device_name,product_key);
		
	mqtt_connect((char *)clientID,(char *)mqttUserName,(char *)deviceToken);
	rt_thread_mdelay(100);
	uint8_t buffer[10]={
    
    0};
	ring_buf_read(&g_uart_rx_buf,sizeof(buffer),buffer);
	if(buffer[0]==0x20 && buffer[3]==0x00)
	{
    
    
		return SUCCESS;
	}
		return ERROR;
}
//连接函数,可以移植,也可以字节编写。以下是自编的。
void mqtt_connect(char *ClientId,char *Username,char *Password)
{
    
    
	uint8_t buffer[256]={
    
    0};
	uint16_t num=0;
	uint8_t Fixed_len = 2;                          //连接报文中,固定报头长度=2
	uint8_t Variable_len = 10;                      //连接报文中,可变报头长度=10
	uint16_t ClientId_len = strlen(ClientId);
	uint16_t Username_len = strlen(Username);
	uint16_t Password_len = strlen(Password);
	uint16_t Payload_len = 2 + ClientId_len + 2 + Username_len + 2 + Password_len; //总报文长度     
		
	/**************************     报头     *************************/
	buffer[num++]=0x10;                         //固定报头第1个字节:0x01	
	uint16_t length =Variable_len + Payload_len;        	
	do
	{
    
    
		char d = length % 128;
		length /= 128;
		/* if there are more digits to encode, set the top bit of this digit */
		if (length > 0)
			d |= 0x80;
		buffer[num++] = d;					//固定报头 :可变报头+有效负荷的长度
	} while (length > 0);
		
	buffer[num++]=0x00;          			//可变报头 :固定0x00	            
	buffer[num++]=0x04;                     //可变报头 :固定0x04
		
	buffer[num++]='M';						//可变报头 :固定0x4D
	buffer[num++]='Q';;						//可变报头 :固定0x51
	buffer[num++]='T';						//可变报头 :固定0x54
	buffer[num++]='T';						//可变报头 :固定0x54
		
	buffer[num++]=0x04;						//可变报头 :固定0x04
	buffer[num++]=0xC2;						//可变报头 :使能用户名和密码校验,不使用遗嘱,不保留会话
	
	buffer[num++]=0x00; 					//可变报头 :保活时间高字节 0x00
	buffer[num++]=0x64;						//可变报头 :保活时间高字节 0x64   100s
		
	/**************************     有效载荷 Payload      *************************/
	/*     CLIENT_ID      */
	buffer[num++] = ClientId_len/256;       //客户端ID长度高字节
	buffer[num++] = ClientId_len%256;       //客户端ID长度低字节
	memcpy(&buffer[num],ClientId,ClientId_len);     //复制客户端ID字串
	num	= num + ClientId_len;
	/*     用户名        */
	buffer[num++] = Username_len/256; 				//用户名长度高字节
	buffer[num++] = Username_len%256; 				//用户名长度低字节
	memcpy(&buffer[num],Username,Username_len);     //复制用户名字串
	num	= num + Username_len;
	/*      密码        */
	buffer[num++] = Password_len/256;			    //密码长度高字节
	buffer[num++] = Password_len%256;			    //密码长度低字节
	memcpy(&buffer[num],Password,Password_len); 	//复制密码字串
	num = num + Password_len;
	HAL_UART_Transmit(&huart1, buffer, num ,100);	
}

猜你喜欢

转载自blog.csdn.net/DJZ1992/article/details/110001332