Paho MQTT 客户端接入阿里云物联网平台(4)| 学习笔记

简介: 快速学习 Paho MQTT 客户端接入阿里云物联网平台(4)

开发者学堂课程【基于STM32的端到端物联网全栈开发Paho MQTT 客户端接入阿里云物联网平台(4)】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/574/detail/7940


Paho MQTT 客户端接入阿里云物联网平台(4)


Paho MQTT 客户端接入阿里云物联网平台示例操作

项目例程软件架构:
应用程序:

1.节点端业务程序

2.阿里云 MQTT 连接适配层

中间件:

1.Paho MQTT embedded C

2.mbedTLSHMAC-SHA1

3.网络接口抽象

底层驱动:

1.STM32L4 Cube HAL 硬件抽象层

2.传感器驱动

3.WIFI 模块驱动

image.png

//例程软件中的 Paho MQTT 协议栈向下通过 ST 提供的网络接口抽象层,来调用底层的 wifi 驱动实现网络数据的通信,向上提供 MQTT API 函数给阿里云 MQTT 连接适配层来完成应用程序的功能

//在接下来的课程中将分别介绍代码中实现网络通信的分层结构,发送和接收数据流的传递过程以及 Paho 向下和网络接口的适配以及向上和阿里云 MQTT 连接适配层的实现

各个软件层中主要对应的c文件以及他们之间的调用关系

---------------1.net_wifi 适配  Wifi 驱动

2.net_c2c 适配 C2c 驱动

3.net_eth 适配 Eth 驱动

image.png

//上边的文件通过下边的软件层通过颜色进行了对应

//节点中的业务程序主要在 main.c 业务中实现

//阿里云 MQTT 连接适配层包括 Ali_iotclient.c 文件和 Ali_iot_network_wrapper.c 文件

//Ali_iotclient.c 文件实现了阿里客户端的功能,包括构建 MQTT 连接的参数,与 MQTT 服务器建立连接,订阅发布消息等函数

//Ali_iot_network_wrapper.c 文件中实现了 MQTT 通信网络接口的封装

//MQTTClient.c Paho 协议栈的文件,它提供了众多 API 给上方的 Ali_iotclient.c 中的函数调用

//net.c 是 ST 的网络接口抽象层的文件,MQTTClient.c 通过 Ali_iot_network_wrapper.c 中封装的网络接口函数向下调用 net.c 中对应的函数,再向下调用 wifi 驱动。在本次例程中只使用到了 wifi 驱动,这个软件结构的好处,是可以很方便的移植到比如2G/3G以及以太网这些网络连接方式去,只需要将 net.c 文件部分下的.c 文件进行替换就能完成,上方的文件代码均不会受到影响。

后端配置代码:    

//AliIoT 路径下有三个适配文件:

Ali_iotclient.c

Ali_iot_network_wrapper.cmqtt_msg_handler.c 文件

// Ali_iot_network_wrapper.c 下封装了5个函数,分别是与服务器创建 tcp 连接,与服务器断开 tcp 连接以及向下对网络接口发送和接收数据的两个函数

//mqtt network 这个函数是在向 mqtt 协议栈新建一个网络接口,并且注册相关的数据收发的函数

// Ali_iotclient.c 文件中主要实现阿里客户端的一些功能,比如如何根据三元组信息来构建 mqtt 服务器的地址,如何得到 mqtt 的主题,如何得到 mqtt 连接的用户名,和 mqtt 连接的密码,还有与 mqtt 服务器创建连接向服务器发送消息和订阅主题的函数

//mqtt 连接创建的过程:

main 函数中,前面的初始化操作和 wifi 都已经连接之后,就会开始与阿里云 iot 平台创建 mqtt 的连接,在 main函数中会调用 connect2Aliiothub 函数,此函数是在 Ali_iotclient.c 文件中实现的,此函数首先会根据三元组的信息来构建 mqtt 服务器的地址。得到服务器的地址后先调用 mqtt_connect_network 函数来与服务器建立 tcp 的连接,此函数是在 Ali_iot_network_wrapper.c 文件中实现的。在 mqtt_connect_network 函数中会调用 net.c 文件中所提供的向上的统一的网络接口函数来实现对网络的一些操作,

首先它会先调用 net_sock_create 来创建一个 socket,在此函数中,他会根据你所使用的不同网络接口来调用对应不同的函数来创建一个 socketsocket 创建成功后,它会将对应的 socket 的操作的函数注册到 sock 结构体中。上层的应用程序来通过 sock 这个结构体来做对应的操作时,实际调用的就是它已经注册的函数。

比如要通过 sock 来进行发送数据,接收输入,那么它调用的就是 net_sock_send_tcp_wifi net_sock_sen_recv_wifi 两个函数,这些函数的实现是在 net.tcp.wifi.c 文件中。mqtt_connect_network 函数首先会创建一个 sock,然后在创建 sock 的过程中,已经注册好一系列对 socket 操作的函数,接收数据,发送数据,断开连接等函数都已经注册成功,然后在对 socket 进行一些配置,最后通过 socket 与服务器建立 tcp 的连接。

#include "main.h"

#include "Ali_iot_network_wrapper.h"

int mqtt_connect_network(letwork* n, const char * host_addressint port)

{

int mqtt_socket_send(Network *network,unsigmed char *bufint len,int timeout){

{

int mqtt_socket_recv(Network *network,unsigmed char *bufint len,int timeout)

{

int mqtt_socket_disconnect(Network *network)

{

//@sz, nev a MQTT netvork interface vith WIFI module

//must called before baidu_connect_netvork_tls/baidu_connect_network

int mqtt_network _new (Network *network)

{

network->my socket = 0;

network->mqttread = mqtt_socket_recv;

network->mqttwrite = mqtt_socket_send;

network->disconnect = mqtt_socket_disconnect;

return SUCCESS;

}

如何构建服务器地址:
extern int PrepareMqttPayload (char * PayloadBuffer,int PayloadSize) ;

extern void Parameters_message_handler(MessageData * data) ;

extern void Service_message_handler(MessageData * data) ;

void calpassword(void) ;

int get_mgtt_server_addr(char* host_addrchar* region_id,char* product_key )

{

//$( YourProductKey}.iot-as-mqtt.$ { YourRegionId}.aliyuncs.com:1883

uint32_t return_len=0;

return_len = snprintf(host_addr,NQTT_CLIENT_INFO_S12E,"4s.iot-a38-mgtt.i8.aliyuncs.com" ,product_key ,regic

n_id) ;

if (return_len >= MQTT_CLIENT_INFO_SIZE)

{

mag_info ("no enough space for host address\n") ;

return -1;

}

msg_info ("MQIT server address is :is\n",host_addr);

return 0;

}

int build_mgtt_topic(void)

{                              

MQTT连接过程:

//WIFI SSID/passov rd config and initializationl

// and config device certificate

ret = initPlatform() ;

if (ret! =0)

{

mag_info ("wifi initial failed! \n");

while(1) ;

// connect to Ali Iot platformret = connect2Aliiothub () :;

if (ret!=0)l

mag_info ("MQIT connection failed! \n");

while(1) ;

}

// subscribe to topicsdeviceSubscribe () ;

/ *USER CODE END 2* /

/*Infinite loop * /

/* USER CODE BEGIN WHILE*/while (1)

{

//MQTT reconnection check

if (rebuildMQTTConnection ( )==0){

doMqttYield( );

/*USER CODE END WHILE*/

int net_sock_create_tcp_wifi(net_hnd_t nethndnet_ockhnd_t * sockhndnet_proto_t proto)

int rc = NET_ERR;

net_ctxt_t *ctxt = (net_ctxt_t *) nethnd;

net_sock_ctxt_t *sock = NULL;

sock = net_malloc (sizeof (net_sock_ctxt_t) );

if (sock == NULL)

mag_error ("net_sock_create allocation failed.in");

rc = NET_ERR;

else

memset (sock, 0, sizeof (net_sock _ctxt_t));sock->net = ctxt;

sock->next = ctxt->sock_list;

sock->methods.create = (net_sock_create_tcp_wifi) ;

sock->methods.open= (net_sock_open_tcp_wifi);

sock->methodg.recv= (net_sock_recv_tcp_wifi);

sock->methoda.send= (net_sock_send_tcp_wifi);

sock->methods.close= (net_sock_close_tcp_wifi) ;

sock->methods.destroy=(net_sock_destroy_tcp_wifi) ;

sock->proto= proto;

sock->blocking= NET_DEFAULT_BLOCKING;

sock->read_timeout= NET_DEFAULT_BLOCKING_READ_TIMEOUT;sock->write_timeout= NET_DEEAULT_BLOCKING_WRITE_TIMEOUT;

ctxt->sock_list= sock; /* Insert at the head of the list */

*sockhnd = (net_sockhnd_t) sock;

rc = NET_OK;

}

return rc;      

网络分层及数据流:

代码中实现网络通信的分层结构,发送和接收数据流的传送过程

//这里所说的网络分层并不是指 tcp 的网络分层,而是指代码中实现网络接口调用程序的时候通过网络接口抽象层,也就是下图中的蓝色部分,将底层实际的网络接口,绿色的 WIFI 驱动部分,与上层的应用程序,黄色的部分独立开,尽量保证底层网络接口的变化不会对上层应用程序产生影响。WIFI 模块驱动也分为了三层,在 emw3080_io.c 文件中是最低层跟外设打交道的部分,包括初始化引脚,从窗口读取和发送数据。

emw3080.c 文件中是对 at 指令的实现。wifi.c wifi 底层驱动和 wifi 网络层面抽象层的接口。从 tcp ip 网络分层的角度,在本例程中的代码仅仅实现了应用层的 mqtt 协议,传输层和网络层都是在 wifi 模块中实现的,从串口传给wifi 模块以及从 wifi 模块接收的都是已经封装完毕的 mqtt 数据包。传输层 tcp 和网络层封装都是由 wifi 模块完成的。

//图中的箭头是接收和发送数据传递的过程

//绿色箭头指发送和接收网络数据,例如发送温湿度信息,接收云端下发的温度阈值。紫色的箭头是 mcu 控制 wifi 模块的 at 指令以及返回值,比如连接 wifi 热点,查询固件版本等等。对于这类指令,只需要将执行的结果返回到上层的应用程序不需要将收到的具体数据向应用层传递。

//图中粉色的变量是数据在传递过程中保存的位置

//应用数据的发送的过程:比如程序要将检测到的温湿度的值从 wifi 发送到云端,应用程序首先会调用 Paho mqtt publish 函数来发送温湿度信息,在 Paho 协议栈中它会将数据封装成数据包的格式并拷贝到 mqtt_write_buf 中,然后通过 mqtt_socket_send 函数向网络接口发送。

通过网络抽象层的函数 net_sock_send net_sock_send_tcp_wifi 来调用 wifi 模块的驱动最后通过EMW3080_IO_Send 函数发送到串口,通过串口发送到 wifi 模块。

//对于云端下发的数据:wifi 模块通过串口将包含温湿度阈值 mqtt 数据包发送,数据首先会保存到 Uart Ring Buffer中,Paho 协议栈中会通过 mqtt 的函数不断的查询是否有新的数据收到,mqtt yarn 的函数会调用 mqtt_socket_recv再通过网络抽象层的函数来调用 WIFI 模块的驱动函数,查询对应的 Socket Buffer 中是否有未读出的数据,如果有就将数据拷贝到 MQTT_read.buf 中,如果则会通过 pullSocktData 函数将串口中 Ring Buffer 新的数据读取到 Socket Buffer 中再拷贝到 MQTT_read_bufMQTT_read_buf 中的数据在 Paho 协议栈中进行分析,再将真正的负载数据,就是温度阈值取出并提供给上层应用程序。

//除了应用数据流的接收,还有连接wifi热点,查询固件版本的 ak 指令的发送和返回值的接收,这部分数据的传递主要在 WIFI 模块驱动这层完成,就是紫色箭头指示的部分,这部分 ak 指令的发送主要在 net_if_int 函数中触发,程序初始化 wifi 模块时调用了 net_interface_ination,然后再此函数中完成 wifi 模块的初始化,wifi 固件版本的查询,以及 wifi 热点连接的工作。

以连接 wifi 热点为例,分析紫色部分传递数据的操作:

连接 wifi 热点是通过调用 WIFI_Connect 函数完成,在这个函数中会调用 emw3080中的函数,在此函数中会进行连接 wifi 热点的 at 指令的组装,然后保存在 Atcmd_buf 中通过 runAtCmd 函数,将数据通过串口发送到 wifi 模块,同时它继续在 runAtCmd 中等待模块发回的at指令返回值,在等待返回值的过程中,通过调用 EMW3080_IO_Receive函数查询串口的 Ring Buffer 中是否收到 wifi 模块的返回值。

问:串口的 Ring Buffer 中既有需要传递到应用层的数据,又有只需要在 WIFI 模块驱动层进行数据处理的数据,程序是如何区分两类数据的呢?

答:wifi 模块在发来的每一个数据都有一定的标识,用来说明这一帧数据的类型,比如 wifi 模块发送从云端收到的温度阈值数据包时,会加上 cip 英文数据的头,从这个标识就可以区分不同的数据包,然后进行数据处理。

网络数据产生/消耗层:Paho

image.png

网络接口:

image.png

WIFI 模块驱动:

image.png

设备端向云端发送数据的过程:

int devicest,atusPub (void)

{

int ret;

MQTTMessage MQTT_mag;

ret =0;

MQTT_msg.qos = Q0S1;  //QoS1 ;

MQTT_msg.dup = 0;//The DUP flag MST be set to 1 by the Client or Server vhen it attemptsto re-deliver a PUBLISH Packet

// The DuP flag MUST be set to 0 for all Qos 0 messages

MQTT_msg.retained = 1; //the Server MJsT store 757 the application Message and its Qos

MQTT_mag.payload = payload_buf;

// TODO:prepare pub payload,@sz

payload_buf [0]= GetTemperaturevalue ( ) ;

payload_buf [1]=GetHumvalue () ;

payload_buf[2]= GetTempratureThreshold( ;

MQTT_mag.payloadlen = 3;

if ( (ret=MQITPublish(zClient,temp_hum_topic, &MQTT_mag)) != 0){

mag_error ("Failed to publish data. td " ,ret) ;

mag_info(": temprature = %d,humidity = %d\n\n",GetTemperatureValue () ,cetHumValue());

}

数据接收的过程:

/**

@brief send data over the vifi connection.

*@paramBuffer: the buffer to send

*@paramLength: the Buffer's data size.

*@retval Returns EMW3080_OK on success and EM3080_ERROR othervise.

*/

EMW3080_StatusTypeDef EMNN3080_SendData(uint8_t socket,uint8_t* Bufferuint32_t Lengthuint32_t Timeout)

EMw3080_statusTypeDef Ret = EMw3080_OK;

if(Buffer != NULL)

uint32_t tickstart;

{

/ *Construct thecommand * /

memset(Atcnd, '1o",MAX_AT_CMD_SIZE);

sprintf( (char * )AtCmd,"AT+CIPSEND=%lu,$lusc", socket,Length,'r');

/ *Tne command doesn't have a return command

until the data is actually sent. Thus ve check here whether

ve got the '>' prompt or not. */

Ret = runAtCmd (AtCmdstrlen ((char *)AtCmd)(uint8_t*)AT_SEND_PROMPT_STRINGTimeout) ;

/ * Return Error */

if (Ret != EMw3080_oK){

return EMN3080_ERROR;

}

/ send the data */

Ret = runAtCmd (Buffer,Length,(uint8_t*)AT_OK_STRINGTimeout) ;

return Ret;

}

驱动和应用层数组定义:

1.Buffer 名称:MQTT_write_buf

默认大小:MQTT_BUFFER_SIZE512字节)
定义所在位置:Ali_iotclient.c
注释:

image.png

2.Buffer 名称:MQTT_read_buf

默认大小:MQTT_BUFFER_SIZE512字节)
定义所在位置:Ali_iotclient.c
注释:

image.png

3.Buffer 名称:AyCmd

默认大小:MAX_AT_SIZE(256字节)
定义所在位置:emw3080.c
注释:

image.png

4.Buffer 名称:RxBuffer

默认大小:MAX_RX_SIZE(1500字节)

定义所在位置:emw3080.c

5.Buffer 名称:WIFIRxBuffer

默认大小: RING_BUFFER_SIZE(1024字节)

定义所在位置:emw3080_io.h

6.Buffer 名称:”sock buffer”

默认大小:MAX_SOCKET_SIZE(512字节)定义所在位置:emw3080.h

WIFI_OpenClientConnection函数中分配内存

Paho MQTT客户端对下(网络连接)的适配

1.  网络接口的适配

typedef struct Network Network;

struct Network

net_sockhnd_t my_socket;

int (*mqttread) (Network*, unsigmed char* , int,int) ;

int (*mqttwrite)(Network* , unsigmed char* , int,int) ;

int (*disconnect)(Network*) ;

};

2.  Timer 的适配

struct Timer {

uint32_t init_tick;

uint32_t timeout_ms;

};

typedef struct Timer Timer;

void TimerCountdownMS(Timer* timerunsigmed int timeout_ms);

void TimerCountdown (Timer* timerunsigmed int timeout);

int TimerLeftMS(Timer* timer);

char TimerIsExpired(Timer* timer);

void TimerInit(Timer* timer) ;

3.  returnCode 枚举与 ST HAL 库的不兼容

Paho MQTT Client 的调用

1.MQTTClientlnit

初始化 MQTT 客户端

2.MQTTConnect

与服务器建立 MQTT 连接

3.MQTTSubscribe

向服务器订阅消息主题,并注册收到消息后的回调函数

4.MQTTPublish

向服务器发布某个主题的消息

5.MQTTYield

根据应用调整周期调用的间隔

Paho MQTT 客户端对上(阿里云 loT)的适配

与阿里云 MQTT 服务器连接需要的参数

1.用户名/密码

2.MQTT ClientID

3.保活时间

4.Cleansession

5.MQTT 服务器域名

typedef struct{

{

/** The eyecatcher for this structure. must be MQTC.*/

char struct_id[4];

/**The version number of this structure.Must be 0 */

int struct_version;

/**version of MQTT to be used. 3 = 3.1 4= 3.1.1

*/

unsigmed char MQITVersion;

MQTTString clientID;

unsigmed short keepAliveInterval;

unsigmed char cleansession;

unsigmed char willElag;

MQTTPacket_wil10ptions will;

MQTTString username;

MQITString password;

}MQTTPacket_connectData;  

构建 MQTT 服务器域名:

MQTT 服务器域名:
${YourProductKey}.iot-as-mqtt.${YourRegionld}.aliyuncs.com:1883

image.png

举例:
1.
服务器域名:

a1b05UeAQ6M.iot-as-mqtt.shanghai-cn.aliyuncs.com

2.端口:1883    

构建 MQTT ClientID

MQTT ClientID: clientld+"[Isecuremode=3,signmethod=hmacsha1,timestamp=132323232

clientld:客户端自己定义的ID号,可以使用 MAC 地址
3:
安全模式,可以选2TLS 直连)和3TCP 直连)

hmacsha1:签名算法支持:

hmacmd5

hmacsha1

hmacsha256
132323232:当前的时间戳。可以通过 HAL_GetTick 获取当前时间戳。

注意:
如果 clientld“b0f8933b9467”',签名算法选择 hmacsha1,当前时间戳为24081

MQTTClientID 为:“b0f8933b9467|securemode=3,signmethod=hmacsha1,timestamp=24081|'    

构建 MQTT 用户名:MQTT 用户名:DeviceName+&+ProductKey

举例:MQTT 用户名就是“smartthermometer&a1b05UeAQ6M”  

构建 MQTT 密码:

MQTT 密码=sign_hmac(DeviceSecret,content)

image.png

Mbedtls:
Demo IAR
工程      

Mbedtls 协议包              

MQTT 主题与消息负载格式:

1.功能:设置温度阈值

MQTT 主题:${productKey}/${deviceName}/tempThresholdSet
操作权限(设备):订阅

消息方向:下行

负载格式:一个字节:温度阈值。直接二进制传输,例如:0x1E 代表30

2.功能:解除警报

MQTT 主题:${productKey}/${deviceName}/clearAlarm
操作权限(设备):订阅

消息方向:下行

负载格式:一个字节,固定位0x01

3.功能:高温报警

MQTT 主题:S{productKey}/${deviceName}/tempAlarm
操作权限(设备):发布

消息方向:上行

负载格式:一个字节,固定位0x01

4.功能:上报属性

MQTT 主题:S{productKey}/${deviceName}/tempHumUpload
操作权限(设备):发布

消息方向:上行

负载格式:  Byte1:温度值

Byte2:湿度值

Byte3:温度阈值

MQTT 订阅消息的回调函数:

image.png

Demo 参数输入:
需要保存在 MCU 闪存中的信息:

1.WIFI 配网参数(串口输入)

2.阿里云 loT 平台三元组信息(串口输入)

3.温度报警阈值(云端下发)      

Demo 参数存储:

1.MCU 用户闪存容量2M,页大小4K(双 bank 下)

2.取末尾32K 作为用户参数存储区

Sensor 数据的读取(1

Sensor 数据的读取(2

项目例程内存占用:

总内存占用(使用 IAR v8.32.3,最高优化等级)

1.Flash52924字节

2.Ram:10874字节(包括4KB 堆栈)

主要模块内存占用:

image.png

相关文章
|
1月前
|
消息中间件 存储 Serverless
【实践】快速学会使用阿里云消息队列RabbitMQ版
云消息队列 RabbitMQ 版是一款基于高可用分布式存储架构实现的 AMQP 0-9-1协议的消息产品。云消息队列 RabbitMQ 版兼容开源 RabbitMQ 客户端,解决开源各种稳定性痛点(例如消息堆积、脑裂等问题),同时具备高并发、分布式、灵活扩缩容等云消息服务优势。
93 2
|
1月前
|
网络协议 物联网 网络性能优化
物联网协议比较 MQTT CoAP RESTful/HTTP XMPP
【10月更文挑战第18天】本文介绍了物联网领域中四种主要的通信协议:MQTT、CoAP、RESTful/HTTP和XMPP,分别从其特点、应用场景及优缺点进行了详细对比,并提供了简单的示例代码。适合开发者根据具体需求选择合适的协议。
53 5
|
1月前
|
存储 边缘计算 物联网
阿里云物联网平台:推动万物互联的智能化解决方案
随着物联网技术的快速发展,阿里云物联网平台为企业提供了一体化的解决方案,包括设备接入、数据管理和智能应用等核心功能。平台支持海量设备接入、实时数据采集与存储、边缘计算,并具备大规模设备管理、高安全性和开放生态等优势。广泛应用于智能制造、智慧城市和智能家居等领域,助力企业实现数字化转型。
181 5
|
2月前
|
消息中间件 弹性计算 运维
阿里云云消息队列RabbitMQ实践解决方案评测报告
阿里云云消息队列RabbitMQ实践解决方案评测报告
76 9
|
2月前
|
网络协议 物联网 网络性能优化
物联网江湖风云变幻!MQTT CoAP RESTful/HTTP XMPP四大门派谁主沉浮?
【9月更文挑战第3天】物联网(IoT)的兴起催生了多种通信协议,如MQTT、CoAP、RESTful/HTTP和XMPP,各自适用于不同场景。本文将对比这些协议的特点、优缺点,并提供示例代码。MQTT轻量级且支持QoS,适合大规模部署;CoAP基于UDP,适用于低功耗网络;RESTful/HTTP易于集成但不适合资源受限设备;XMPP支持双向通信,适合复杂交互应用。通过本文,开发者可更好地选择合适的物联网通信协议。
40 2
|
3月前
|
物联网 C# 智能硬件
智能家居新篇章:WPF与物联网的智慧碰撞——通过MQTT协议连接与控制智能设备,打造现代科技生活的完美体验
【8月更文挑战第31天】物联网(IoT)技术的发展使智能家居设备成为现代家庭的一部分。通过物联网,家用电器和传感器可以互联互通,实现远程控制和状态监测等功能。本文将探讨如何在Windows Presentation Foundation(WPF)应用中集成物联网技术,通过具体示例代码展示其实现过程。文章首先介绍了MQTT协议及其在智能家居中的应用,并详细描述了使用Wi-Fi连接方式的原因。随后,通过安装Paho MQTT客户端库并创建MQTT客户端实例,演示了如何编写一个简单的WPF应用程序来控制智能灯泡。
122 0
|
3月前
|
物联网 网络性能优化 Python
"掌握MQTT协议,开启物联网通信新篇章——揭秘轻量级消息传输背后的力量!"
【8月更文挑战第21天】MQTT是一种轻量级的消息传输协议,以其低功耗、低带宽的特点在物联网和移动应用领域广泛应用。基于发布/订阅模型,MQTT支持三种服务质量级别,非常适合受限网络环境。本文详细阐述了MQTT的工作原理及特点,并提供了使用Python `paho-mqtt`库实现的发布与订阅示例代码,帮助读者快速掌握MQTT的应用技巧。
90 0
|
30天前
|
消息中间件 JSON Java
开发者如何使用轻量消息队列MNS
【10月更文挑战第19天】开发者如何使用轻量消息队列MNS
72 4
|
25天前
|
消息中间件 存储 Kafka
MQ 消息队列核心原理,12 条最全面总结!
本文总结了消息队列的12个核心原理,涵盖消息顺序性、ACK机制、持久化及高可用性等内容。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
消息中间件 安全 Java
云消息队列RabbitMQ实践解决方案评测
一文带你详细了解云消息队列RabbitMQ实践的解决方案优与劣
72 7

相关产品

  • 物联网平台
  • 下一篇
    无影云桌面