MQTT客户端二次封装,基于paho(Java)

首先看使用方式:

pom.xml添加依赖:

<dependency>
    <groupId>net.oschina.durcframework</groupId>
    <artifactId>paho-mqtt-client</artifactId>
    <version>1.0.0</version>
</dependency>

源码地址

使用方式

建立连接设置自动重连

PahoMqttClient mqttClient = PahoMqttClient.create()
    .broker(broker)
    .auth(username, password)
    .clientId(clientId)
    .cleanSession(true)
    // 自动重连
    .automaticReconnect(true)
    // 订阅消息
    .subscribe(topic, 2)
    // 设置回调,处理消息    
    .callback(new MyMqttCallback())
    .connect();


public static class MyMqttCallback extends PahoMqttCallback {

    @Override
    public void connectionLost(Throwable throwable) {
        System.out.println("[client]失去连接:" + throwable.getMessage());
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        System.out.println("[client]收到消息: topic:" + topic + ", msg:" + mqttMessage.toString());
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

    }
}

如果要发送消息,调用publish方法

mqttClient.publish(upLocationTopic, location.getBytes(), 1);

测试用例

这里使用车联网作为测试场景,汽车终端设备每隔一段时间上报定位,IOT平台每隔一段时间下发OTA升级指令。

IOT平台实现功能如下:

  • 订阅定位上报topic,接收设备上报的定位数据
  • 发送OTA消息到汽车终端

汽车终端设备实现功能如下:

  • 订阅点对点topic,接收平台端下发的指令
  • 订阅定位上报topic,上报定位信息

IOT平台功能代码

package com.gitee.mqttclient;

import com.gitee.mqttclient.callback.PahoMqttCallback;
import com.gitee.mqttclient.client.PahoMqttClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * 模拟平台端
 * @author thc
 */
public class ServerTest {

    protected static String broker = "tcp://1.1.1.1:1883";
    protected static String username = "s001";
    protected static String password = "xxx";

    static PahoMqttClient mqttClient;


    /**
     * 启动平台端
     * @throws InterruptedException
     * @throws MqttException
     */
    @Test
    public void server() throws InterruptedException, MqttException {
        String clientId = "server-node-1";
        // 平台端监听所有车型定位topic
        String topic = "prod/+/+/base/location/#";
        mqttClient = PahoMqttClient.create()
                .broker(broker)
                .auth(username, password)
                .clientId(clientId)
                .cleanSession(true)
                // 自动重连
                .automaticReconnect(true)
                // 订阅消息
                .subscribe(topic, 1)
                .callback(new ServerMqttCallback())
                .connect();

        // 另起一个线程,进行指令下发
        new Thread(() -> {
            // 每隔20秒对A000001这辆车进行OTA升级
            String downTopic = "o2o/A000001/ota";
            while (true) {
                String otaContent = String.valueOf(System.currentTimeMillis());
                System.out.println("发送ota指令:" + otaContent);
                byte[] otaFile = otaContent.getBytes();
                try {
                    mqttClient.publish(downTopic, otaFile, 2);
                } catch (MqttException e) {
                    throw new RuntimeException(e);
                }
                try {
                    TimeUnit.SECONDS.sleep(20);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        TimeUnit.DAYS.sleep(1);
    }

    /**
     * 服务端接收消息回调
     */
    public static class ServerMqttCallback extends PahoMqttCallback {

        @Override
        public void connectionLost(Throwable throwable) {
            System.out.println("[server]失去连接:" + throwable.getMessage());
        }

        @Override
        public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
            System.out.println("[server]收到消息: topic:" + topic + ", msg:" + mqttMessage.toString());
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

        }
    }

}

汽车终端功能代码

package com.gitee.mqttclient;

import com.gitee.mqttclient.callback.PahoMqttCallback;
import com.gitee.mqttclient.client.PahoMqttClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.junit.Test;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 模拟设备端,汽车终端
 * @author thc
 */
public class ClientTest {

    protected static String broker = "tcp://1.1.1.1:1883";
    protected static String username = "u001";
    protected static String password = "xxx";

    // 汽车类型
    static String carType = "suv";
    // 车架号
    static String vin = "A000001";

    // 格式:client-用户名-车架号
    static String clientId = "client-" + username + "-" + vin;


    private static PahoMqttClient mqttClient;

    private void init() throws MqttException {
        // 订阅点对点消息
        String topic = "o2o/" + vin + "/+";
        mqttClient = PahoMqttClient.create()
                .broker(broker)
                .auth(username, password)
                .clientId(clientId)
                .cleanSession(true)
                // 自动重连
                .automaticReconnect(true)
                // 订阅消息
                .subscribe(topic, 2)
                .callback(new MyMqttCallback())
                .connect();
    }

    @Test
    public void device() throws InterruptedException {
        try {
            init();
        } catch (MqttException me) {
            System.err.println("MQTT连接失败");
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("excep " + me);
            me.printStackTrace();
            return;
        }

        // 另起一个线程,上报信息
        new Thread(() -> {
            // 上报定位topic
            String upLocationTopic = String.format("prod/%s/%s/base/location", carType, vin);

            // 每隔10秒上报一次定位信息
            while (true) {
                try {
                    // 随机经纬度
                    String lon = "120.123" + new Random().nextInt(100);
                    String lat = "30.123" + new Random().nextInt(100);
                    String location = lon + "," + lat;
                    System.out.println("上报定位信息:" + location);
                    // 上报经纬度
                    mqttClient.publish(upLocationTopic, location.getBytes(), 1);
                } catch (MqttException e) {
                    throw new RuntimeException(e);
                }
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        // stop here
        TimeUnit.DAYS.sleep(1);
    }

    public static class MyMqttCallback extends PahoMqttCallback {

        @Override
        public void connectionLost(Throwable throwable) {
            System.out.println("[client]失去连接:" + throwable.getMessage());
        }

        @Override
        public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
            System.out.println("[client]收到消息: topic:" + topic + ", msg:" + mqttMessage.toString());
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

        }
    }


}

broker, username, password改成自己的

先执行平台端测试用例,在执行设备端测试用例。

源码地址

### 回答1: MQTT(消息队列遥测传输)是一种轻量级的通信协议,常用于物联网设备之间的通信。 以下是使用C语言编写的MQTT客户端代码,使用了Paho库进行二次封装: ```c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <MQTTClient.h> #define MQTT_SERVER "tcp://localhost:1883" #define MQTT_TOPIC "topic/test" #define MQTT_QOS 0 void messageArrived(void *context, char *topicName, int topicLen, MQTTClient_message *message) { char* payload = malloc(message->payloadlen + 1); strncpy(payload, message->payload, message->payloadlen); payload[message->payloadlen] = '\0'; printf("Message received: %s\n", payload); free(payload); MQTTClient_freeMessage(&message); MQTTClient_free(topicName); } int main() { MQTTClient client; MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; MQTTClient_message pubmsg = MQTTClient_message_initializer; MQTTClient_deliveryToken token; conn_opts.keepAliveInterval = 20; conn_opts.cleansession = 1; MQTTClient_create(&client, MQTT_SERVER, "ClientID", MQTTCLIENT_PERSISTENCE_NONE, NULL); MQTTClient_setCallbacks(client, NULL, NULL, messageArrived, NULL); int rc; if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) { printf("Failed to connect, return code %d\n", rc); exit(-1); } MQTTClient_subscribe(client, MQTT_TOPIC, MQTT_QOS); char* payload = "Hello, MQTT!"; pubmsg.payload = payload; pubmsg.payloadlen = strlen(payload); pubmsg.qos = MQTT_QOS; pubmsg.retained = 0; MQTTClient_publishMessage(client, MQTT_TOPIC, &pubmsg, &token); MQTTClient_waitForCompletion(client, token, 1000); sleep(1); MQTTClient_disconnect(client, 1000); MQTTClient_destroy(&client); return 0; } ``` 以上代码创建了一个MQTT客户端,连接到本地的MQTT服务器。订阅了"topic/test"主题,接收到消息时会调用`messageArrived`函数进行处理。 在主函数中,先建立连接并订阅主题,然后发出一条消息"Hello, MQTT!"发布到指定主题。 最后,等待1秒后断开连接并销毁客户端。 这个示例代码演示了如何使用Paho库进行MQTT客户端开发,并进行了一次消息发布和订阅的操作。 ### 回答2: MQTT是一种轻量级的通信协议,常用于物联网设备之间的通信。paho库是一个开源MQTT实现库,可以在各种编程语言中使用。下面是使用C语言进行MQTT客户端编程的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "MQTTClient.h" #define ADDRESS "tcp://mqtt.eclipse.org:1883" #define CLIENTID "ExampleClientPub" #define TOPIC "MQTT Examples" #define QOS 1 #define TIMEOUT 10000L void delivered(void *context, MQTTClient_deliveryToken dt) { printf("Message with token value %d delivery confirmed\n", dt); } int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) { printf("Message arrived\n"); printf(" topic: %s\n", topicName); printf(" message: "); for (int i = 0; i < message->payloadlen; i++) { putchar(((char *)message->payload)[i]); } putchar('\n'); MQTTClient_freeMessage(&message); MQTTClient_free(topicName); return 1; } void connlost(void *context, char *cause) { printf("\nConnection lost\n"); printf(" cause: %s\n", cause); } int main() { MQTTClient client; MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; int rc; MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); conn_opts.keepAliveInterval = 20; conn_opts.cleansession = 1; MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered); if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) { printf("Failed to connect, return code %d\n", rc); exit(-1); } MQTTClient_subscribe(client, TOPIC, QOS); char payload[100]; sprintf(payload, "Hello MQTT!"); MQTTClient_message pubmsg = MQTTClient_message_initializer; pubmsg.payload = payload; pubmsg.payloadlen = strlen(payload); pubmsg.qos = QOS; pubmsg.retained = 0; MQTTClient_deliveryToken token; if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS) { printf("Failed to publish message, return code %d\n", rc); exit(-1); } printf("Waiting for publication to be acknowledged...\n"); if ((rc = MQTTClient_waitForCompletion(client, token, TIMEOUT)) != MQTTCLIENT_SUCCESS) { printf("Failed to receive acknowledgement, return code %d\n", rc); exit(-1); } printf("Message published\n"); MQTTClient_disconnect(client, TIMEOUT); MQTTClient_destroy(&client); return 0; } ``` 上述代码使用了paho库来连接到`mqtt.eclipse.org`的公共MQTT服务器,并发送和接收消息。在`main`函数中,首先创建了一个`MQTTClient`对象,然后设置了连接选项并建立了连接。接着订阅了一个主题,用于接收消息。然后构造了一个要发布的消息,然后使用`MQTTClient_publishMessage`方法将消息发布到指定的主题上,并监听发布结果是否被确认。最后,断开了与服务器的连接并销毁了`MQTTClient`对象。 这是一个非常简单的MQTT客户端示例,可以根据具体需求进行二次封装和扩展。 ### 回答3: 以下是一个使用paho库和二次封装MQTT客户端C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "MQTTClient.h" #define ADDRESS "tcp://mqtt.eclipse.org:1883" #define CLIENTID "ExampleClient" #define TOPIC "mqtt/topic" #define QOS 1 #define TIMEOUT 10000L typedef void (*message_callback_t)(char *topic, char *payload); void messageArrived(MessageData *data) { char topic[64]; char payload[64]; strncpy(topic, data->topicName->lenstring.data, data->topicName->lenstring.len); topic[data->topicName->lenstring.len] = '\0'; strncpy(payload, data->message->payload, data->message->payloadlen); payload[data->message->payloadlen] = '\0'; message_callback_t cb = (message_callback_t)data->message->mqtt->userData; cb(topic, payload); } void sendMessage(MQTTClient client, char *topic, char *payload) { MQTTMessage message = MQTTMessage_initializer; message.qos = QOS; message.retained = 0; message.payload = payload; message.payloadlen = strlen(payload); MQTTClient_publishMessage(client, topic, &message, NULL); } void subscribeToTopic(MQTTClient client, char *topic, message_callback_t cb) { MQTTClient_subscribe(client, topic, QOS); MQTTClient_setCallbacks(client, cb, NULL, messageArrived, NULL); } void disconnectClient(MQTTClient client) { MQTTClient_disconnect(client, TIMEOUT); MQTTClient_destroy(&client); } int main(int argc, char* argv[]) { MQTTClient client; MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; int rc; rc = MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); if (rc != MQTTCLIENT_SUCCESS) { printf("Failed to create MQTT client, return code %d\n", rc); exit(EXIT_FAILURE); } conn_opts.keepAliveInterval = 20; conn_opts.cleansession = 1; rc = MQTTClient_connect(client, &conn_opts); if (rc != MQTTCLIENT_SUCCESS) { printf("Failed to connect, return code %d\n", rc); exit(EXIT_FAILURE); } printf("Connected to MQTT broker\n"); // 订阅主题并指定消息回调函数 subscribeToTopic(client, TOPIC, messageCallback); // 发送消息 sendMessage(client, TOPIC, "Hello, MQTT!"); // 断开连接 disconnectClient(client); return rc; } ``` 这个例子使用paho库创建一个MQTT客户端,连接到指定的MQTT代理服务器。它订阅一个主题并指定一个消息回调函数来处理接收到的消息。然后,它发送一条消息到指定的主题上,并最终断开连接。你可以根据自己的需求修改其中的主题、服务器地址、客户端ID等参数,并在`message_callback_t`函数中处理接收到的消息。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值