【OpenHarmony成长计划挑战赛】基于Openarmony的碳侦测无人机:MQTT - HarmonyOS技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

[文章]

【OpenHarmony成长计划挑战赛】基于Openarmony的碳侦测无人机:MQTT

MQTT联网演示

本案例程序将演示编写一个连接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
	  */
	unsigned char MQTTVersion;
	MQTTString clientID;
	unsigned short keepAliveInterval;
	unsigned char cleansession;
	unsigned char willFlag;
	MQTTPacket_willOptions will;
	MQTTString username;
	MQTTString password;
} MQTTPacket_connectData;

述:

MQTT客户端连接参数

参数:

名字 描述
MQTTVersion MQTT协议版本号
clientID 用户ID
keepAliveInterval 保活周期
cleansession 是否清除session信息
willFlag 是否使用临终遗言
will 临终遗言信息
username 用户名
password 用户密钥

示例代码如下:

// 连接参数
MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 
// 客户ID,唯一
data.clientID.cstring= "Talkweb";   
// 不使用临终遗言
data.willFlag = 0; 
// MQTT版本号
data.MQTTVersion = 3; 
// 保存存活时间
data.keepAliveInterval = 0; 
// 重新连接后是否清除以前的信息 0表示不清除,1表示重连清除
data.cleansession = 1;
// 服务器用户名
data.username.cstring = "Talkweb"; 
// 服务器用户密码
data.password.cstring = "Talkweb1996";
typedef struct MQTTMessage
{
    enum QoS qos;
    unsigned char retained;
    unsigned char dup;
    unsigned short id;
    void *payload;
    size_t payloadlen;
} MQTTMessage;

描述:

MQTT消息结构体

参数:

名字 描述
qos 服务等级
retained 是否保留
dup 重发标识
id 消息id
payload 消息数据
payloadlen 消息数据长度

函数详解

void NetworkInit(Network* n)

描述: 初始化网络

参数:

名字 描述
n 要初始化的Network结构体
int NetworkConnect(Network* n, char* addr, int port)

描述:

连接MQTT服务器

参数:

名字 描述
n 已经初始化的Network.
addr MQTT服务器IP地址
port MQTT服务器端口
void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size)

描述:

MQTT客户端初始化

参数:

名字 描述
c MQTTClient客户端
network 网络结构体
command_timeout_ms 延时毫秒
sendbuf 发送内容数组
sendbuf_size 发送内容数组长度
readbuf 接收内容数组
readbuf_size 接收内容数组长度
int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)

描述:

MQTT客户端连接服务器

参数:

名字 描述
c MQTT客户端
options 连接参数 详细参数请查看上面定义
int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos,
       messageHandler messageHandler)

描述:

订阅主题

参数:

名字 描述
c MQTT客户端
topicFilter 订阅的主题
qos 订阅质量
00:最多一次,即:<=1
01:至少一次,即:>=1
10:一次,即:=1
11:预留
messageHandler 消息处理回调函数
int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)

描述:

订阅主题

参数:

名字 描述
c MQTT客户端
topicName 发布的主题
message MQTTMessage 消息

软件设计

主要代码分析

static void MQTTDemoTask(void)
{
    // 连接WIFI
    WifiConnect(SELECT_WIFI_SSID, SELECT_WIFI_PASSWORD);
    printf("Starting ...\n");
    int rc, count = 0;
    MQTTClient client;

    // 初始化网络参数
    NetworkInit(&network);
    printf("NetworkConnect  ...\n");
begin:
    // 连接服务器网络
    NetworkConnect(&network, "123.60.8.120", 1883);
    printf("MQTTClientInit  ...\n");
    // 初始化客户端
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    // 连接参数
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 
    // 客户ID,唯一
    data.clientID.cstring= "Talkweb";   
    // 不使用临终遗言
    data.willFlag = 0; 
    // MQTT版本号
    data.MQTTVersion = 3; 
    // 保存存活时间
    data.keepAliveInterval = 0; 
    // 重新连接后是否清除以前的信息 0表示不清除,1表示重连清除
    data.cleansession = 1;
    // 服务器用户名
    data.username.cstring = "Talkweb"; 
    // 服务器用户密码
    data.password.cstring = "Talkweb1996"; 

    printf("MQTTConnect  ...\n");
    // 登录服务器
    rc = MQTTConnect(&client, &data);
    // 失败处理
    if (rc != 0) {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(200);
        goto begin;
    }

    printf("MQTTSubscribe  ...\n");
    // 订阅主题,并绑定回调函数处理接收到的消息
    rc = MQTTSubscribe(&client, "pubtopic", 2, MessageArrived);
    // 订阅失败处理
    if (rc != 0) {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(200);
        goto begin;
    }
    while (count++) {
        MQTTMessage message;
        // 发布的内容
        char payload[] = {"{\"name\": \"Talkweb\",\"url\": \"https://www.talkweb.com.cn/\"}"};
        // 仅一次
        message.qos = 2;
        message.retained = 0;
        message.payload = payload;
        message.payloadlen = strlen(payload);
        // 发布
        if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            goto begin;
        }
        osDelay(100);
    }
    
}

编译调试

修改对接热点的账号密码

修改mqtt_main.h第32行和33行的WiFi热点SSID和密码,改成自己环境中的WiFi热点。

// 默认WiFi名和密码
#define SELECT_WIFI_SSID "*****"
#define SELECT_WIFI_PASSWORD "*******"

修改 BUILD.gn 文件

修改 applications/app/BUILD.gn 路径中的 BUILD.gn 文件,指定 network_mqttclient_example 参与编译。

# "TW208_Module_ds1307:module_ds1307_example",
# "TW209_Module_gps:module_gps_example",
# "TW301_Network_wifista:network_wifista_example",
# "TW302_Network_wifiap:network_wifiap_example",
"TW303_Network_mqttclient:network_mqttclient_example",
# "TW304_Network_httpclient:network_httpclient_example",
# "TW305_Network_ntpclient:network_ntpclient_example",

运行结果

示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,会打印连接到的Wifi热点信息,以及订阅MQTT服务器主题,并接收发布后返回的结果。

Starting ...
NetworkConnect  ...
MQTTClientInit  ...
MQTTConnect  ...
MQTTSubscribe  ...
wait for suback
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}

自己搭建MQTT服务器,用于测试。测试步骤如下: 1、下载apache-apollo-1.7.1搭建本地mqtt服务器,用于接入测试。工具使用参考:2、获取本地IP地址,并把本地IP地址和端口61613替换案例中的地址。替换MQTTDemoTask函数中的NetworkConnect(&network, "为自己地址"); 3、对应修改服务器用户名和密码,替换为apollo的默认用户名和密码:admin,password。 4、为了方便测试,可以把本地电脑,开发板连接同一个网络。 5、正常显示如下:

NetworkConnect  ...                                                                                         
MQTTClientInit  ...                                                                                        
MQTTConnect  ...                                                                                             
MQTTSubscribe  ...                                                                                           
wait for suback                                                                                         
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}

更多回帖

×
发帖