onenet中mqtt示例程序的学习(一)——Mqtt_PackConnectPkt函数及之前

betball贝博app stm32 669 次浏览 没有评论

硬件方面初始化完毕,进入MQTT_Loop函数,开始进行MQTT的一系列操作。

进入以后,MqttSample_Init(smpctx)初始化MQTT,就是配置一系列的设备ID,产品ID等等。

然后通过Mqtt_InitContext(ctx->mqttctx, 1 << 8);初始化一个8字节的上下文变量,设置了首地址,尾地址等等。进而进行回调函数的初始化。

但是,对于回调函数的初始化中,每一个函数名都还跟了一个“回调函数的关联参数”,目前不懂这个是什么意思。例如:
[cce_cpp]
ctx->mqttctx->read_func = MqttSample_RecvPkt;
ctx->mqttctx->writev_func = MqttSample_SendPkt;

ctx->mqttctx->handle_conn_ack = MqttSample_HandleConnAck;
ctx->mqttctx->handle_conn_ack_arg = ctx;//不知道什么意思
ctx->mqttctx->handle_ping_resp = MqttSample_HandlePingResp;
ctx->mqttctx->handle_ping_resp_arg = ctx;

[/cce_cpp]
然后通过MqttBuffer_Init(ctx->mqttbuf);初始化缓冲器变量。

至此,MQTT初始化完毕,开始MQTT的连接。进入MqttSample_CmdConnect函数。


/**
* @brief 发送MQTT Connet报文,登录鉴权
* @param ctx:上下文变量
* @retval ret:0,成功,<0 失败
**/
static int MqttSample_CmdConnect(struct MqttSampleContext *ctx)


首先,打包一个MQTT连接报文,对比分析调用函数和函数原型。

Mqtt_PackConnectPkt(ctx->mqttbuf, 0, ctx->devid, 1, MQTT_DEVICE_PROJ_ID,
MQTT_DEVICE_AUTH_INFO, strlen(MQTT_DEVICE_AUTH_INFO), MQTT_QOS_LEVEL0, 0, ctx->proid,
ctx->apikey, strlen(ctx->apikey));

int Mqtt_PackConnectPkt(struct MqttBuffer *buf, uint16_t keep_alive, const char *id,int clean_session, const char *will_topic,const char *will_msg, uint16_t msg_len,enum MqttQosLevel qos, int will_retain, const char *user,const char *password, uint16_t pswd_len)
几个参数的对应关系如下:
strlen(MQTT_DEVICE_AUTH_INFO)  MQTT_QOS_LEVEL0    0           ctx->proidctx->apikeystrlen(ctx->apikey)
id——devid//设备ID
will_topic——MQTT_DEVICE_PROJ_ID//产品ID
will_msg——MQTT_DEVICE_AUTH_INFO//auth鉴权信息
user—— ctx->proid//产品ID-和topic相同!
password——ctx->apikey
该函数内部,声明并赋值了多个标志位,和报文的各个部分存放变量。
wt_len为will_topic(产品ID)的长度
struct MqttExtent *fix_head, *variable_head, *payload;
固定报头和可变报头分别分配了5,10个字节。
size_t total_len;该变量为有效载荷的长度,因为其无符号,所以赋初值为10,后面再减去。
total_len = 10; //可变报头的长度
total_len += 4 + wt_len + msg_len;即4+产品ID长度+鉴权信息的长度
通过读取是否存在各个变量,判断各个标志位的值,将标志位依次加到flag中,从而组成了最终的标志位。
下面语句,为有效载荷分配空间,然后确定固定报头的载荷内容,调整固定报头的长度。
此处为连接MQTT服务器,则可变报头的内容为固定的
(00 04(长度) 4D 51 54 54(协议名) 04(协议级别) C0(连接标志) 00 78(120s keeplive))
[cce_cpp]
    payload = MqttBuffer_AllocExtent(buf, total_len - 10);//可变报头的长度初始值赋值为10,此处再减去10
    fix_head->payload[0] = MQTT_PKT_CONNECT << 4;
    ret = Mqtt_DumpLength(total_len, fix_head->payload + 1);
    if(ret < 0)
    {
        return MQTTERR_PKT_TOO_LARGE;
    }
    fix_head->len = ret + 1; // ajust the length of the extent

    variable_head->payload[0] = 0;
    variable_head->payload[1] = 4;
    variable_head->payload[2] = 'M';
    variable_head->payload[3] = 'Q';
    variable_head->payload[4] = 'T';
    variable_head->payload[5] = 'T';
    variable_head->payload[6] = 4; // protocol level 4
    variable_head->payload[7] = flags;
    Mqtt_WB16(keep_alive, variable_head->payload + 8);
[/cce_cpp]
将ID复制到有效载荷中,再依次写入各种变量。不再一一列举。
[cce_cpp]
cursor = payload->payload;
Mqtt_PktWriteString(&cursor, id, id_len);
[/cce_cpp]
 各个报文组好,将内容填充至变量中
[cce_cpp]
    MqttBuffer_AppendExtent(buf, fix_head);
    MqttBuffer_AppendExtent(buf, variable_head);
    MqttBuffer_AppendExtent(buf, payload);
[/cce_cpp]
由此,Mqtt_PackConnectPkt函数结束,消息内容已经填充至ctx->mqttbuf变量中。

然后执行Mqtt_SendPkt(ctx->mqttctx, ctx->mqttbuf, 0);


发表评论

邮箱地址不会被公开。

Go