rtthread studio + STM32实现MQTT协议自动接入ONENET STUDIO

2023-10-23 22:30

本文主要是介绍rtthread studio + STM32实现MQTT协议自动接入ONENET STUDIO,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

创建并配置工程

MQTT接入代码流程

 user id查看方法

 project id查看方法

用户鉴权信息计算方法

device鉴权信息计算方法

鉴权计算C语言实现代码

base64.c

 hmac_sha1.c

onenet_token.c

 onenet_studio_http_register_device() 实现

 onenet_studio_get_register_device_data() 实现

onenet_studio_upload_register_device() 实现

onenet_studio_response_register_handlers() 实现

onenet_studio_upload_add_device() 实现

ONENET MQTT订阅主题生成函数topic_generate() 实现:

onenet mqtt主题format:

 函数实现

在onenet_mqtt_entry()中添加相关代码

strstrpl()实现


硬件平台:【正点原子】阿波罗STM32F429开发板

集成开发环境:rtthread studio

实现功能:实现开机自动接入onenet studio,在指定账号下创建设备并加入指定项目

创建并配置工程

1、打开rtthread studio,点击菜单栏,文件——新建——RTthread项目——基于开发板

2、选择STM32F429-ATK-APOLLO开发板

3、创建工程完成后,点击RT-Thread Setting

 

 4、点击添加软件包

 5、搜索并添加onenet软件包

 6、配置onenet软件包,使能onenet自动注册设备,使能MQTT协议,填写产品ID、主/产品 APIKEY,(注册码随意填,接入ONENET STUDIO用不上)

7、点击”硬件“选项卡,使能 W25Q256、使能Ethernet


        rtthread onenet packet包适配onenet云平台的多协议接入的MQTT协议接入,但不适配onenet云平台新出的onenet studio的MQTT协议接入,因此需要在源码的基础上稍作修改,如下所示:

MQTT接入代码流程

(绿色:源码已有;蓝色:源码已有,自己实现;红色:源码未有,自己实现)

 user id查看方法

1、登录ONENET平台

2、点击账号信息可查看user id

                          

 project id查看方法

1、进入onenet studio界面

  

2、选择应用开发——项目管理

3、创建项目后可查看project id

用户鉴权信息计算方法

安全鉴权_开发者文档_OneNET (10086.cn)https://open.iot.10086.cn/doc/iot_platform/book/api/auth.html

device鉴权信息计算方法

接入安全认证_开发者文档_OneNET (10086.cn)https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/device-auth.html

鉴权计算C语言实现代码

base64.c

#include "base64.h"#include <stdint.h>
#include <stdio.h>#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */static const unsigned char base64_enc_map[64] =
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T','U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd','e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n','o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x','y', 'z', '0', '1', '2', '3', '4', '5', '6', '7','8', '9', '+', '/'
};static const unsigned char base64_dec_map[128] =
{127, 127, 127, 127, 127, 127, 127, 127, 127, 127,127, 127, 127, 127, 127, 127, 127, 127, 127, 127,127, 127, 127, 127, 127, 127, 127, 127, 127, 127,127, 127, 127, 127, 127, 127, 127, 127, 127, 127,127, 127, 127,  62, 127, 127, 127,  63,  52,  53,54,  55,  56,  57,  58,  59,  60,  61, 127, 127,127,  64, 127, 127, 127,   0,   1,   2,   3,   4,5,   6,   7,   8,   9,  10,  11,  12,  13,  14,15,  16,  17,  18,  19,  20,  21,  22,  23,  24,25, 127, 127, 127, 127, 127, 127,  26,  27,  28,29,  30,  31,  32,  33,  34,  35,  36,  37,  38,39,  40,  41,  42,  43,  44,  45,  46,  47,  48,49,  50,  51, 127, 127, 127, 127, 127
};/*
************************************************************
*   brief:  BASE64_Encode
*
*   function    Base64编码
*
*   parames:    dst: 保存数据的缓冲区
*               dlen:保存数据的缓存区长度
*               olen:记录写入字节数
*               src:   输入数据
*               slen:输入数据长度
*
*   return:     0-success
************************************************************
*/
int BASE64_Encode(  unsigned char   *dst,size_t          dlen,size_t          *olen,const unsigned char *src,size_t          slen     )
{size_t i = 0, n = 0;int C1 = 0, C2 = 0, C3 = 0;unsigned char *p = (void *)0;if(slen == 0){*olen = 0;return 0;}n = slen / 3 + (slen % 3 != 0);if(n > (BASE64_SIZE_T_MAX - 1) / 4){*olen = BASE64_SIZE_T_MAX;return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;}n *= 4;if((dlen < n + 1) || (NULL == dst)){*olen = n + 1;return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;}n = (slen / 3) * 3;for(i = 0, p = dst; i < n; i += 3){C1 = *src++;C2 = *src++;C3 = *src++;*p++ = base64_enc_map[(C1 >> 2) & 0x3F];*p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];*p++ = base64_enc_map[C3 & 0x3F];}if(i < slen){C1 = *src++;C2 = ((i + 1) < slen) ? *src++ : 0;*p++ = base64_enc_map[(C1 >> 2) & 0x3F];*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];if((i + 1) < slen)*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];else *p++ = '=';*p++ = '=';}*olen = p - dst;*p = 0;return 0;}/*
************************************************************
*	brief:	BASE64_Decode
*
*	function	Base64解码
*
*	parames:	dst: 保存数据的缓冲区
*				dlen:保存数据的缓存区长度
*				olen:记录写入字节数
*				src:   输入数据
*				slen: 输入数据长度
*
*	return:	    0-success
************************************************************
*/
int BASE64_Decode(unsigned char *dst, size_t dlen, size_t *olen,const unsigned char *src, size_t slen)
{size_t i = 0, n = 0;uint32_t j = 0, x = 0;unsigned char *p = (void *)0;/* First pass: check for validity and get output length */for(i = n = j = 0; i < slen; i++){/* Skip spaces before checking for EOL */x = 0;while(i < slen && src[i] == ' '){++i;++x;}/* Spaces at end of buffer are OK */if(i == slen)break;if((slen - i) >= 2 &&src[i] == '\r' && src[i + 1] == '\n')continue;if(src[i] == '\n')continue;/* Space inside a line is an error */if(x != 0)return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;if(src[i] == '=' && ++j > 2)return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;if(src[i] > 127 || base64_dec_map[src[i]] == 127)return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;if(base64_dec_map[src[i]] < 64 && j != 0)return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;n++;}if(n == 0){*olen = 0;return 0;}/*  The following expression is to calculate the following formula withoutrisk of integer overflow in n:n = ( ( n * 6 ) + 7 ) >> 3;*/n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3);n -= j;if(dst == NULL || dlen < n){*olen = n;return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;}for(j = 3, n = x = 0, p = dst; i > 0; i--, src++){if(*src == '\r' || *src == '\n' || *src == ' ')continue;j -= (base64_dec_map[*src] == 64);x  = (x << 6) | (base64_dec_map[*src] & 0x3F);if(++n == 4){n = 0;if(j > 0)*p++ = (unsigned char)(x >> 16);if(j > 1)*p++ = (unsigned char)(x >>  8);if(j > 2)*p++ = (unsigned char)(x);}}*olen = p - dst;return 0;}

 hmac_sha1.c


#include "hmac_sha1.h"#include <stdlib.h>
#include <stdio.h>int test_case_length[] = {9, 8, 28, 50, 50, 20, 54, 73, 54, 73};unsigned char test_cases[] =
{/* "Sample #1" */0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x23, 0x31,/* "Hi There"   */0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65,/* "what do ya want for nothing?" */0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61,0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20,0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3f,0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,/* "Test With Truncation" */0x54, 0x65, 0x73, 0x74, 0x20, 0x57, 0x69, 0x74, 0x68, 0x20, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61,0x74, 0x69, 0x6f, 0x6e,/* "Test Using Larger Than Block-Size Key - Hash Key First" */0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,0x20, 0x46, 0x69, 0x72, 0x73, 0x74,/* "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" */0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72,0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d,0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74, 0x61,/* "Test Using Larger Than Block-Size Key - Hash Key First" */0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,0x20, 0x46, 0x69, 0x72, 0x73, 0x74,/* "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" */0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72,0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d,0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74, 0x61
};int key_lengths[] =
{64, 20, 4, 20, 25, 20, 80, 80, 80, 80
};unsigned char keys[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,0x0b, 0x0b, 0x0b, 0x0b,0x4a, 0x65, 0x66, 0x65, /* "Jefe" */0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,0x15, 0x16, 0x17, 0x18, 0x19,0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};/*****************************/
/**** Function Prototypes ****/
/*****************************/unsigned long int ft(int t,unsigned long int x,unsigned long int y,unsigned long int z
);int get_testcase(int test_case,unsigned char *plaintext,unsigned char *key,int *key_length_ptr);void sha1(unsigned char *message,int message_length,unsigned char *digest
);/**************************/
/* Debug out              */
/**************************/#ifdef HMAC_DEBUG
debug_out(unsigned char *label,unsigned char *data,int data_length
){int i, j;int num_blocks;int block_remainder;num_blocks = data_length / 16;block_remainder = data_length % 16;printf("%s\n", label);for(i = 0; i < num_blocks; i++){printf("\t");for(j = 0; j < 16; j++){printf("%02x ", data[j + (i * 16)]);}printf("\n");}if(block_remainder > 0){printf("\t");for(j = 0; j < block_remainder; j++){printf("%02x ", data[j + (num_blocks * 16)]);}printf("\n");}
}
#endif/****************************************/
/* sha1()                               */
/* Performs the NIST SHA-1 algorithm    */
/****************************************/unsigned long int ft(int t,unsigned long int x,unsigned long int y,unsigned long int z
){unsigned long int a, b, c;if(t < 20){a = x & y;b = (~x) &z;c = a ^ b;}else if(t < 40){c = x ^ y ^ z;}else if(t < 60){a = x & y;b = a ^ (x & z);c = b ^ (y & z);}else if(t < 80){c = (x ^ y) ^z;}return c;
}unsigned long int k(int t){unsigned long int c;if(t < 20){c = 0x5a827999;}else if(t < 40){c = 0x6ed9eba1;}else if(t < 60){c = 0x8f1bbcdc;}else if(t < 80){c = 0xca62c1d6;}return c;
}unsigned long int rotr(int bits, unsigned long int a){unsigned long int c, d, e, f, g;c = (0x0001 << bits) - 1;d = ~c;e = (a & d) >> bits;f = (a & c) << (32 - bits);g = e | f;return (g & 0xffffffff);
}unsigned long int rotl(int bits, unsigned long int a){unsigned long int c, d, e, f, g;c = (0x0001 << (32 - bits)) - 1;d = ~c;e = (a & c) << bits;f = (a & d) >> (32 - bits);g = e | f;return (g & 0xffffffff);
}void sha1(unsigned char *message,int message_length,unsigned char *digest
){int i;int num_blocks;int block_remainder;int padded_length;unsigned long int l;unsigned long int t;unsigned long int h[5];unsigned long int a, b, c, d, e;unsigned long int w[80];unsigned long int temp;
#ifdef SHA1_DEBUGint x, y;
#endif/* Calculate the number of 512 bit blocks */padded_length = message_length + 8; /* Add length for l */padded_length = padded_length + 1; /* Add the 0x01 bit postfix */l = message_length * 8;num_blocks = padded_length / 64;block_remainder = padded_length % 64;if(block_remainder > 0){num_blocks++;}padded_length = padded_length + (64 - block_remainder);/* clear the padding field */for(i = message_length; i < (num_blocks * 64); i++){message[i] = 0x00;}/* insert b1 padding bit */message[message_length] = 0x80;/* Insert l */message[(num_blocks * 64) - 1] = (unsigned char)(l        & 0xff);message[(num_blocks * 64) - 2] = (unsigned char)((l >> 8)  & 0xff);message[(num_blocks * 64) - 3] = (unsigned char)((l >> 16) & 0xff);message[(num_blocks * 64) - 4] = (unsigned char)((l >> 24) & 0xff);/* Set initial hash state */h[0] = 0x67452301;h[1] = 0xefcdab89;h[2] = 0x98badcfe;h[3] = 0x10325476;h[4] = 0xc3d2e1f0;
#ifdef SHA1_DEBUGprintf("INITIAL message_length = %d\n", message_length);printf("INITIAL padded_length = %d\n", padded_length);printf("INITIAL num_blocks = %d\n", num_blocks);for(x = 0; x < num_blocks; x++){printf("\t\t");for(y = 0; y < 16; y++){printf("%02x ", message[y + (x * 64)]);}printf("\n");printf("\t\t");for(y = 0; y < 16; y++){printf("%02x ", message[16 + y + (x * 64)]);}printf("\n");printf("\t\t");for(y = 0; y < 16; y++){printf("%02x ", message[32 + y + (x * 64)]);}printf("\n");printf("\t\t");for(y = 0; y < 16; y++){printf("%02x ", message[48 + y + (x * 64)]);}printf("\n");}#endiffor(i = 0; i < num_blocks; i++){/* Prepare the message schedule */for(t = 0; t < 80; t++){if(t < 16){w[t]  = (256 * 256 * 256) * message[(i * 64) + (t * 4)];w[t] += (256 * 256) * message[(i * 64) + (t * 4) + 1];w[t] += (256) * message[(i * 64) + (t * 4) + 2];w[t] +=                 message[(i * 64) + (t * 4) + 3];}else if(t < 80){w[t] = rotl(1, (w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]));}}#ifdef SHA1_DEBUGprintf("\tW(0) = %08lX \t W(9)  = %08lX \n", w[0], w[8]);printf("\tW(1) = %08lX \t W(10) = %08lX \n", w[1], w[9]);printf("\tW(2) = %08lX \t W(11) = %08lX \n", w[2], w[10]);printf("\tW(3) = %08lX \t W(12) = %08lX \n", w[3], w[11]);printf("\tW(4) = %08lX \t W(13) = %08lX \n", w[4], w[12]);printf("\tW(5) = %08lX \t W(14) = %08lX \n", w[5], w[13]);printf("\tW(6) = %08lX \t W(15) = %08lX \n", w[6], w[14]);printf("\tW(7) = %08lX \t W(16) = %08lX \n\n", w[7], w[15]);
#endif/* Initialize the five working variables */a = h[0];b = h[1];c = h[2];d = h[3];e = h[4];/* iterate a-e 80 times */for(t = 0; t < 80; t++){temp = (rotl(5, a) + ft(t, b, c, d)) & 0xffffffff;temp = (temp + e) & 0xffffffff;temp = (temp + k(t)) & 0xffffffff;temp = (temp + w[t]) & 0xffffffff;e = d;d = c;c = rotl(30, b);b = a;a = temp;
#ifdef SHA1_DEBUGprintf("t = %2ld\t %08lx, %08lx, %08lx, %08lx, %08lx\n", t, a, b, c, d, e);
#endif}/* compute the ith intermediate hash value */
#ifdef SHA1_DEBUGprintf("  +   \t %08lx, %08lx, %08lx, %08lx, %08lx\n", h[0], h[1], h[2], h[3], h[4]);
#endifh[0] = (a + h[0]) & 0xffffffff;h[1] = (b + h[1]) & 0xffffffff;h[2] = (c + h[2]) & 0xffffffff;h[3] = (d + h[3]) & 0xffffffff;h[4] = (e + h[4]) & 0xffffffff;
#ifdef SHA1_DEBUGprintf("  =   \t %08lx, %08lx, %08lx, %08lx, %08lx\n", h[0], h[1], h[2], h[3], h[4]);
#endif}digest[3]  = (unsigned char)(h[0]       & 0xff);digest[2]  = (unsigned char)((h[0] >> 8) & 0xff);digest[1]  = (unsigned char)((h[0] >> 16) & 0xff);digest[0]  = (unsigned char)((h[0] >> 24) & 0xff);digest[7]  = (unsigned char)(h[1]       & 0xff);digest[6]  = (unsigned char)((h[1] >> 8) & 0xff);digest[5]  = (unsigned char)((h[1] >> 16) & 0xff);digest[4]  = (unsigned char)((h[1] >> 24) & 0xff);digest[11]  = (unsigned char)(h[2]       & 0xff);digest[10]  = (unsigned char)((h[2] >> 8) & 0xff);digest[9] = (unsigned char)((h[2] >> 16) & 0xff);digest[8] = (unsigned char)((h[2] >> 24) & 0xff);digest[15] = (unsigned char)(h[3]       & 0xff);digest[14] = (unsigned char)((h[3] >> 8) & 0xff);digest[13] = (unsigned char)((h[3] >> 16) & 0xff);digest[12] = (unsigned char)((h[3] >> 24) & 0xff);digest[19] = (unsigned char)(h[4]       & 0xff);digest[18] = (unsigned char)((h[4] >> 8) & 0xff);digest[17] = (unsigned char)((h[4] >> 16) & 0xff);digest[16] = (unsigned char)((h[4] >> 24) & 0xff);
}/******************************************************/
/* hmac-sha1()                                        */
/* Performs the hmac-sha1 keyed secure hash algorithm */
/******************************************************/void hmac_sha1(unsigned char *key,int key_length,unsigned char *data,int data_length,unsigned char *digest
){int b = 64; /* blocksize */unsigned char ipad = 0x36;unsigned char opad = 0x5c;unsigned char k0[64];unsigned char k0xorIpad[64];unsigned char step7data[64];unsigned char step5data[MAX_MESSAGE_LENGTH + 128];unsigned char step8data[64 + 20];int i;for(i = 0; i < 64; i++){k0[i] = 0x00;}if(key_length != b)     /* Step 1 */{/* Step 2 */if(key_length > b){sha1(key, key_length, digest);for(i = 0; i < 20; i++){k0[i] = digest[i];}}else if(key_length < b)   /* Step 3 */{for(i = 0; i < key_length; i++){k0[i] = key[i];}}}else{for(i = 0; i < b; i++){k0[i] = key[i];}}#ifdef HMAC_DEBUGdebug_out("k0", k0, 64);
#endif/* Step 4 */for(i = 0; i < 64; i++){k0xorIpad[i] = k0[i] ^ ipad;}#ifdef HMAC_DEBUGdebug_out("k0 xor ipad", k0xorIpad, 64);
#endif/* Step 5 */for(i = 0; i < 64; i++){step5data[i] = k0xorIpad[i];}for(i = 0; i < data_length; i++){step5data[i + 64] = data[i];}#ifdef HMAC_DEBUGdebug_out("(k0 xor ipad) || text", step5data, data_length + 64);
#endif/* Step 6 */sha1(step5data, data_length + b, digest);
#ifdef HMAC_DEBUGdebug_out("Hash((k0 xor ipad) || text)", digest, 20);
#endif/* Step 7 */for(i = 0; i < 64; i++){step7data[i] = k0[i] ^ opad;}#ifdef HMAC_DEBUGdebug_out("(k0 xor opad)", step7data, 64);
#endif/* Step 8 */for(i = 0; i < 64; i++){step8data[i] = step7data[i];}for(i = 0; i < 20; i++){step8data[i + 64] = digest[i];}#ifdef HMAC_DEBUGdebug_out("(k0 xor opad) || Hash((k0 xor ipad) || text)", step8data, 20 + 64);
#endif/* Step 9 */sha1(step8data, b + 20, digest);
#ifdef HMAC_DEBUGdebug_out("HASH((k0 xor opad) || Hash((k0 xor ipad) || text))", digest, 20);
#endif
}

onenet_token.c

/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2021-09-30     hands       the first version*/
#include "rtthread.h"
#include "base64.h"
#include "hmac_sha1.h"
#include "md5.h"
#include "misc.h"
#include "stdint.h"#define DBG_ENABLE
#define DBG_COLOR
#define DBG_SECTION_NAME    "onenet.token"
#define DBG_LEVEL           DBG_INFO
#include <rtdbg.h>/*
************************************************************
*   函数名称:   UrlEncode
*
*   函数功能:   sign需要进行URL编码
*
*   入口参数:   str:输入字符串
*
*   返回参数:   0-成功    其他-失败
*
*   说明:             +           %2B
*               空格                 %20
*               /           %2F
*               ?           %3F
*               %           %25
*               #           %23
*               &           %26
*               =           %3D
*   注意,使用完后记得释放返回的内存,否则会造成内存泄漏
************************************************************
*/
static char* UrlEncode(char *str)
{uint32_t i = 0, j = 0;uint32_t str_len = 0;uint32_t extra_malloc_bytes = 0;char *dest = RT_NULL;if(str == (void *)0)return RT_NULL;str_len = rt_strlen(str);while(str[i] != '\0'){switch(str[i++]){case '+':extra_malloc_bytes += 2;break;case ' ':extra_malloc_bytes += 2;break;case '/':extra_malloc_bytes += 2;break;case '?':extra_malloc_bytes += 2;break;case '%':extra_malloc_bytes += 2;break;case '#':extra_malloc_bytes += 2;break;case '&':extra_malloc_bytes += 2;break;case '=':extra_malloc_bytes += 2;break;default:break;}}extra_malloc_bytes = str_len + extra_malloc_bytes + 1;dest = rt_malloc(extra_malloc_bytes);rt_memset(dest, 0, extra_malloc_bytes);if(dest != RT_NULL){LOG_D("%s malloc len: %d",__FUNCTION__, extra_malloc_bytes);for(i = 0, j = 0; str[i] != '\0'; i++){switch(str[i]){case '+':strcat(dest + j, "%2B");j += 3;break;case ' ':strcat(dest + j, "%20");j += 3;break;case '/':strcat(dest + j, "%2F");j += 3;break;case '?':strcat(dest + j, "%3F");j += 3;break;case '%':strcat(dest + j, "%25");j += 3;break;case '#':strcat(dest + j, "%23");j += 3;break;case '&':strcat(dest + j, "%26");j += 3;break;case '=':strcat(dest + j, "%3D");j += 3;break;default:dest[j++] = str[i];break;}}dest[j] = 0;}else {LOG_E("function: %s line: %s: malloc fail",__FUNCTION__, __LINE__);}return dest;
}char* token_generate_res_4_login(const char *product_id, const char* device_id)
{
#define token_res_format        "products/{pid}/devices/{device_name}"char *src = RT_NULL;char *res = RT_NULL;if(product_id == RT_NULL || device_id == RT_NULL)   return RT_NULL;src = strrpl(token_res_format, "{pid}", product_id);if(src != RT_NULL){res = strrpl(src, "{device_name}", device_id);rt_free(src);}return res;
}/*
************************************************************
*   函数名称:   OTA_Authorization
*
*   函数功能:   计算Authorization
*
*   入口参数:      version:参数组版本号,日期格式,目前仅支持格式"2018-10-31"
*               product_id:产品id
*               device_id:  设备id
*               et:过期时间,UTC秒值
*               access_key:访问密钥
*               authorization_buf:缓存token的指针
*               authorization_buf_len:缓存区长度(字节)
*
*   返回参数:   0-成功    其他-失败
*
*   说明:     当前仅支持sha1
************************************************************
*/
rt_err_t token_calculate(   char            *version,const char      *res,unsigned int    et,char            *access_key,char            *authorization_buf,unsigned short  authorization_buf_len,char*           method                  )
{size_t   olen    = 0;rt_err_t    err     = RT_EOK;char sign_buf[64] = { 0 };              //保存签名的Base64编码结果 和 URL编码结果char encrypt_buf[64] = { 0 };           //保存签名char access_key_base64[64] = { 0 };     //保存access_key的Base64编码结合char string_for_signature[128] = { 0 }; //保存string_for_signature,这个是加密的keychar* res_url = 0;char* sign_url = 0;if(version == (void *)0 || method == (void*)0 || et < 1564562581 || access_key == (void *)0|| authorization_buf == (void *)0 || authorization_buf_len < 128)return -1;//----------------------------------------------------Base64decode(access_key)----------------------------------------------------LOG_D("access_key: %s\tlen: %d", access_key, strlen(access_key));rt_memset(access_key_base64, 0, sizeof(access_key_base64));err = BASE64_Decode((unsigned char *)access_key_base64, sizeof(access_key_base64), &olen, (const unsigned char *)access_key, rt_strlen(access_key));if(err == RT_EOK){LOG_D("base64_decode(access_key): %x", access_key_base64);}else {LOG_E("base64 decode fail.err code %x",err);err = -RT_ERROR;goto _exit;}//----------------------------------------------------calculate string_for_signature-----------------------------------------------------rt_memset(string_for_signature, 0, sizeof(string_for_signature));rt_snprintf(string_for_signature, sizeof(string_for_signature), "%u\n%s\n%s\n%s", et, method, res, version);LOG_D("string_for_signature: %s\r\n", string_for_signature);/* generate sign start  *///----------------------------------------------------加密-------------------------------------------------------------------------if(rt_strcmp(method, "sha1") == 0){rt_memset(encrypt_buf, 0, sizeof(encrypt_buf));hmac_sha1((unsigned char *)access_key_base64, rt_strlen(access_key_base64),(unsigned char *)string_for_signature, rt_strlen(string_for_signature),(unsigned char *)encrypt_buf);LOG_D("hmac_sha1_buf: %x\r\n", encrypt_buf);}else if(rt_strcmp(method, "md5") == 0){LOG_D("the method %s haven't been supported.",method);err = -RT_EINVAL;goto _exit;}else{LOG_D("the method %s haven't been supported.",method);err = -RT_EINVAL;goto _exit;}//----------------------------------------------------将加密结果进行Base64编码------------------------------------------------------olen = 0;rt_memset(sign_buf, 0, sizeof(sign_buf));BASE64_Encode((unsigned char *)sign_buf, sizeof(sign_buf), &olen, (unsigned char *)encrypt_buf, rt_strlen(encrypt_buf));LOG_D("base64_encode(sign): %s\r\n", sign_buf);//----------------------------------------------------将生成的sign进行URL编码---------------------------------------------------sign_url = UrlEncode(sign_buf);LOG_D("url_encode(base64_encode(sign)): %s", sign_url);//----------------------------------------------------将生成的res进行URL编码---------------------------------------------------res_url = UrlEncode(res);LOG_D("url_encode(res): %s", res_url);//----------------------------------------------------生成Token--------------------------------------------------------------------rt_snprintf(authorization_buf, authorization_buf_len, "version=%s&res=%s&et=%u&method=%s&sign=%s", version, res_url, et, method, sign_url);LOG_D("Token: \r\n %s", authorization_buf);_exit:if(res_url){rt_free(res_url);}if(sign_url){rt_free(sign_url);}return err;
}

 onenet_studio_http_register_device() 实现

/*** Register device to OneNET cloud.** @param   name            device name* @param   auth_info       authentication information** @return  0 : register device success*         -5 : no memory*/
rt_err_t onenet_studio_http_register_device(const char *name, const char *auth_info)
{char *send_buffer = RT_NULL;rt_err_t result = RT_EOK;RT_ASSERT(name);RT_ASSERT(auth_info);send_buffer = (char *) ONENET_CALLOC(1, ONENET_SEND_DATA_LEN);if (!send_buffer){LOG_E("ONENET register device failed! No memory for send buffer!");return -RT_ENOMEM;}/* get JSON format data */result = onenet_studio_get_register_device_data(name, auth_info, send_buffer);if (result < 0){goto __exit;}/* send data to cloud by HTTP */result = onenet_studio_upload_register_device(send_buffer);if (result < 0){goto __exit;}__exit:if (send_buffer){ONENET_FREE(send_buffer);}return result;
}

 onenet_studio_get_register_device_data() 实现

static rt_err_t onenet_studio_get_register_device_data(const char *ds_name, const char *auth_info, char *out_buff)
{rt_err_t result = RT_EOK;cJSON *root = RT_NULL;char *msg_str = RT_NULL;RT_ASSERT(ds_name);RT_ASSERT(auth_info);RT_ASSERT(out_buff);root = cJSON_CreateObject();if (!root){LOG_E("MQTT register device failed! cJSON create object error return NULL!");return -RT_ENOMEM;}cJSON_AddStringToObject(root, "product_id", ONENET_INFO_PROID);cJSON_AddStringToObject(root, "device_name", ds_name);/* render a cJSON structure to buffer */msg_str = cJSON_PrintUnformatted(root);if (!msg_str){LOG_E("Device register device failed! cJSON print unformatted error return NULL!");result = -RT_ENOMEM;goto __exit;}strncpy(out_buff, msg_str, strlen(msg_str));__exit:if (root){cJSON_Delete(root);}if (msg_str){ONENET_FREE(msg_str);}return result;
}

onenet_studio_upload_register_device() 实现

/* upload register device data to Onenet cloud */
static rt_err_t onenet_studio_upload_register_device(char *send_buffer)
{struct webclient_session *session = RT_NULL;char *buffer = send_buffer;char *URI = RT_NULL;size_t length = 0;unsigned char *rec_buf = RT_NULL;rt_err_t result = RT_EOK;char *res = RT_NULL;char *token_buf = RT_NULL;RT_ASSERT(send_buffer);session = webclient_session_create(ONENET_HTTP_HEAD_LEN);if (session == RT_NULL){result = -RT_ERROR;goto __exit;}URI = (char *) ONENET_CALLOC(1, ONENET_CON_URI_LEN);if (URI == RT_NULL){LOG_E("OneNet register device failed! No memory for URI buffer!");result = -RT_ENOMEM;goto __exit;}rt_snprintf(URI, ONENET_CON_URI_LEN, ONENET_STUDIO_API_createDevice);res = strrpl("userid/{userid}", "{userid}", ONENET_USER_ID);if(res == RT_NULL){LOG_E("<%s> res generate failed", __FUNCTION__);result = -RT_ERROR;goto __exit;}LOG_D("res: %s", res);token_buf =  (char *) ONENET_CALLOC(1, ONENET_INFO_AUTH_LEN);if(token_buf == RT_NULL){LOG_E("<%s> <%s> malloc failed", __FUNCTION__, __LINE__);result = -RT_ENOMEM;goto __exit;}rt_memset(token_buf, 0, ONENET_INFO_AUTH_LEN);token_calculate("2020-05-29",res,_get_nettme_unix(),ONENET_USER_ACCESS_KEY,token_buf,ONENET_INFO_AUTH_LEN,"sha1");if(token_buf[0] == '0'){LOG_E("token calculate fail.");result = -RT_ERROR;goto __exit;}WEBCLIENT_HEADER_ADD(session, "Authorization: %s\r\n", token_buf);WEBCLIENT_HEADER_ADD(session, "Content-Type: application/json\r\n");WEBCLIENT_HEADER_ADD(session, "Content-Length: %d\r\n", strlen(buffer));LOG_D("Body:\r\n%s",buffer);if (webclient_post(session, URI, buffer) != 200){result = -RT_ERROR;goto __exit;}rec_buf = (unsigned char *) ONENET_CALLOC(1, ONENET_RECV_RESP_LEN);if (rec_buf == RT_NULL){LOG_E("OneNet register device failed! No memory for response data buffer!");result = -RT_ENOMEM;goto __exit;}length = webclient_read(session, rec_buf, ONENET_RECV_RESP_LEN);if (length > 0){onenet_studio_response_register_handlers(rec_buf, length);}else{LOG_E("OneNet register device failed! Handle response(%d) error!", session->resp_status);}__exit:if (session){webclient_close(session);}if (URI){ONENET_FREE(URI);}if (rec_buf){ONENET_FREE(rec_buf);}if(res){ONENET_FREE(res);}if(result == RT_EOK){result = onenet_studio_upload_add_device(token_buf, buffer);}if(token_buf){ONENET_FREE(token_buf);}return result;
}

onenet_studio_response_register_handlers() 实现

static rt_err_t onenet_studio_response_register_handlers(const unsigned char *rec_buf, const size_t length)
{CJSON_PUBLIC(cJSON *) root = RT_NULL;CJSON_PUBLIC(cJSON *) item = RT_NULL;CJSON_PUBLIC(cJSON *) msg  = RT_NULL;CJSON_PUBLIC(cJSON *) itemid = RT_NULL;CJSON_PUBLIC(cJSON *) itemapikey = RT_NULL;rt_err_t err = RT_EOK;RT_ASSERT(rec_buf);LOG_D("response is %.*s", length, rec_buf);root = cJSON_Parse((char *)rec_buf);if (!root){LOG_E("onenet register device failed! cJSON Parse data error return NULL!");err = -RT_ENOMEM;goto __exit;}item = cJSON_GetObjectItem(root, "success");if(item == RT_NULL){LOG_E("item %s not found", "success");err = -RT_ERROR;goto __exit;}if (item->valueint == 1){itemid = cJSON_GetObjectItem(root->child, "name");itemapikey = cJSON_GetObjectItem(root->child, "sec_key");if(itemid != RT_NULL && itemapikey != RT_NULL){onenet_port_save_device_info(itemid->valuestring, itemapikey->valuestring);}}else{msg = cJSON_GetObjectItem(root, "msg");if(msg != RT_NULL){if(rt_strcmp(msg->valuestring, "device name already exist") == 0){goto __exit;}}LOG_E("onenet register device failed! errno is %d", item->valueint);err = -RT_ERROR;goto __exit;}__exit:if(root){cJSON_free(root);}return err;
}

onenet_studio_upload_add_device() 实现

static rt_err_t onenet_studio_upload_add_device(char *token, char *send_buffer)
{struct webclient_session *session = RT_NULL;char *URI = RT_NULL;size_t length = 0;unsigned char *rec_buf = RT_NULL;rt_err_t result = RT_EOK;char *msg_str = RT_NULL;CJSON_PUBLIC(cJSON *) root = RT_NULL;CJSON_PUBLIC(cJSON *) post_body = RT_NULL;CJSON_PUBLIC(cJSON *) device_name = RT_NULL;CJSON_PUBLIC(cJSON *) dev_id_arry = RT_NULL;session = webclient_session_create(ONENET_HTTP_HEAD_LEN);if (session == RT_NULL){LOG_E("create session fail. %s", __LINE__);result = -RT_ERROR;goto __exit;}/* �峰��device_id & product_id */root = cJSON_Parse((char *)send_buffer);if(root == RT_NULL){result = -RT_ERROR;goto __exit;}device_name = cJSON_GetObjectItem(root, "device_name");if(device_name == RT_NULL){LOG_E("device id not found. %s", __LINE__);result = -RT_ERROR;goto __exit;}/* �����ユ�� */post_body = cJSON_CreateObject();if(post_body == RT_NULL){result = -RT_ERROR;LOG_E("create cjson object fail. %s", __LINE__);goto __exit;}cJSON_AddStringToObject(post_body, "project_id", ONENET_STUDIO_PROJECT_ID);cJSON_AddStringToObject(post_body, "product_id", ONENET_INFO_PROID);dev_id_arry = cJSON_AddArrayToObject(post_body, "devices");cJSON_InsertItemInArray(dev_id_arry, 0, device_name);msg_str = cJSON_PrintUnformatted(post_body);if (!msg_str){LOG_E("Device add device failed! cJSON print unformatted error return NULL!");result = -RT_ENOMEM;goto __exit;}LOG_D("Body:\r\n%s",msg_str);WEBCLIENT_HEADER_ADD(session, "Authorization: %s\r\n", token);WEBCLIENT_HEADER_ADD(session, "Content-Type: application/json\r\n");WEBCLIENT_HEADER_ADD(session, "Content-Length: %d\r\n", strlen(msg_str));URI = (char *) ONENET_CALLOC(1, ONENET_CON_URI_LEN);if (URI == RT_NULL){LOG_E("OneNet register device failed! No memory for URI buffer!");result = -RT_ENOMEM;goto __exit;}rt_snprintf(URI, ONENET_CON_URI_LEN, ONENET_STUDIO_API_AddDevice);rec_buf = (unsigned char *) ONENET_CALLOC(1, ONENET_RECV_RESP_LEN);if (rec_buf == RT_NULL){LOG_E("OneNet register device failed! No memory for response data buffer!");result = -RT_ENOMEM;goto __exit;}if (webclient_post(session, URI, msg_str) != 200){result = -RT_ERROR;goto __exit;}length = webclient_read(session, rec_buf, ONENET_RECV_RESP_LEN);if (length > 0){LOG_D("response is %.*s", length, rec_buf);}else{LOG_E("OneNet register device failed! Handle response(%d) error!", session->resp_status);}__exit:if(msg_str){ONENET_FREE(msg_str);}if(post_body){cJSON_free(post_body);}if(root){cJSON_free(root);}if (session){webclient_close(session);}if (URI){ONENET_FREE(URI);}if (rec_buf){ONENET_FREE(rec_buf);}return result;
}

ONENET MQTT订阅主题生成函数topic_generate() 实现:

onenet mqtt主题format:


/*                                                    ONENET STUDIO TOPICS DEFINE                                              */
/* 1、设备属性上报 */
#define onenet_public_property_post              "$sys/{pid}/{device-name}/thing/property/post"            //上行:设备属性上报
#define onenet_subscribe_property_post_reply     "$sys/{pid}/{device-name}/thing/property/post/reply"      //下行:设备属性上报回复
/* 2、设备属性设置 */
#define onenet_subscribe_property_set            "$sys/{pid}/{device-name}/thing/property/set"             //下行: 设备属性设置
#define onenet_public_property_set_reply         "$sys/{pid}/{device-name}/thing/property/set_reply"       //上行:设备属性设置回复
/* 3、设备属性获取 */
#define onenet_subscribe_property_get            "$sys/{pid}/{device-name}/thing/property/get"             //下行:设备属性获取
#define onenet_public_property_get_reply         "$sys/{pid}/{device-name}/thing/property/get_reply"       //上行:设备属性获取回复
/* 4、设备事件上报 */
#define onenet_public_event_post                 "$sys/{pid}/{device-name}/thing/event/post"               //上行:设备事件上报
#define onenet_subscribe_event_post_reply        "$sys/{pid}/{device-name}/thing/event/post/reply"         //下行:设备事件上报回复

 函数实现

int topic_generate(char *str_dev_name,char* str_product_id)
{char* src = RT_NULL;if(topic_property_post == RT_NULL){src = strrpl(onenet_public_property_post, "{pid}", str_product_id);topic_property_post = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}if(topic_property_post_reply == RT_NULL){src = strrpl(onenet_subscribe_property_post_reply, "{pid}", str_product_id);topic_property_post_reply = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}if(topic_property_set == RT_NULL){src = strrpl(onenet_subscribe_property_set, "{pid}", str_product_id);topic_property_set = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}if(topic_property_set_reply == RT_NULL){src = strrpl(onenet_public_property_set_reply, "{pid}", str_product_id);topic_property_set_reply = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}if(topic_event_post == RT_NULL){src = strrpl(onenet_public_event_post, "{pid}", str_product_id);topic_event_post = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}if(topic_event_post_reply == RT_NULL){src = strrpl(onenet_subscribe_event_post_reply, "{pid}", str_product_id);topic_event_post_reply = strrpl(src, "{device-name}", str_dev_name);if(src)rt_free(src);}LOG_D("topic: \r\n property post:\t%s \r\n ""property post reply:\t%s \r\n ""property set:\t%s \r\n ""property set reply:\t%s \r\n ""event post: \t%s \r\n ""event post reply: \t%s \r\n ",topic_property_post,topic_property_post_reply,topic_property_set,topic_property_set_reply,topic_event_post,topic_event_post_reply);return RT_EOK;
}

在onenet_mqtt_entry()中添加相关代码

    topic_generate(name,pro_id);
#endiftopic = get_topic_property_post_reply();if(topic != RT_NULL){mq_client.messageHandlers[0].topicFilter = topic;mq_client.messageHandlers[0].qos = 1;mq_client.messageHandlers[0].callback = mqtt_callback;}topic = get_topic_property_set();if(topic != RT_NULL){mq_client.messageHandlers[1].topicFilter = topic;mq_client.messageHandlers[1].qos = 1;mq_client.messageHandlers[1].callback = onenet_topic_property_set_reply_cb;}topic = get_topic_event_post_reply();if(topic != RT_NULL){mq_client.messageHandlers[2].topicFilter = topic;mq_client.messageHandlers[2].qos = 1;mq_client.messageHandlers[2].callback = mqtt_callback;}

strstrpl()实现

/**      function:*         在str中搜索str1,并使用str2进行替换,申请内存储存替换之后的字符串并返回首地址*      params:*          str:    需要搜索的字符串*          str1:   被替换的字符串*          str2:   替换的字符串*      return:*          替换str1之后的字符串(申请内存)*/
char* strrpl(char *str,char *str1,char *str2)
{uint32_t count = 0;char        *tmp        = str;char        *tmp_dest   = RT_NULL;char        *src        = str;char        *dest       = RT_NULL;int         malloc_len  = 0;uint32_t    str_len     = rt_strlen(str);uint32_t    str1_len    = rt_strlen(str1);uint32_t    str2_len    = rt_strlen(str2);while( *src++ )  // 检测cp字符串在str字符串中的个数{tmp = rt_strstr(tmp, str1);if( tmp == RT_NULL ){break;}count ++;tmp += str1_len;if(tmp > (str + str_len)){break;}}if(count == 0){LOG_D("%s not found in %s",str1, str);return RT_NULL;}malloc_len = str_len + 1 + count*((long)(str2_len - str1_len));if(malloc_len <= 0){LOG_D("");return RT_NULL;}dest = rt_malloc(malloc_len);tmp = str;tmp_dest = dest;count = 0;while(count < malloc_len && *tmp != '\0'){if(rt_strncmp(tmp, str1, rt_strlen(str1)) == 0){src = str2;if(src != 0){while( *src != '\0' ){*(tmp_dest++) = *(src++);count++;}}tmp = tmp + str1_len;if(tmp >= str + str_len)    break;}else{*(tmp_dest++) = *(tmp++);count++;}}*(dest + count) = '\0';return dest;
}

这篇关于rtthread studio + STM32实现MQTT协议自动接入ONENET STUDIO的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/270844

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现