ROS C++ MQTT通讯实例示例

8 篇文章 0 订阅
2 篇文章 1 订阅

ROS C++ MQTT通讯实例示例

本文从以下几个方面进行说明:

  • MQTT C++ Client Library 安装
  • Linux C++ 发布端代码
  • Linux C++ 订阅端代码

关于MQTT开发环境的搭建,详见:

使用EMQX 安装、部署MQTT 服务器详解

https://blog.csdn.net/limeigui/article/details/125676842?spm=1001.2014.3001.5502

1. MQTT C++ Client Library 安装

参考: https://github.com/eclipse/paho.mqtt.cpp

1.1. install doxygen

Building the documentation requires doxygen and optionally graphviz to be installed:

$ sudo apt-get install doxygen graphviz

1.2. Building the Paho C library

 Before building the C++ library, first, build and install the Paho C library, if not already present. Note, this version of the C++ library requires Paho C v1.3.8 or greater.
$ git clone https://github.com/eclipse/paho.mqtt.c.git
$ cd paho.mqtt.c
$ git checkout v1.3.8

$ cmake -Bbuild -H. -DPAHO_ENABLE_TESTING=OFF -DPAHO_BUILD_STATIC=ON \
    -DPAHO_WITH_SSL=ON -DPAHO_HIGH_PERFORMANCE=ON
$ sudo cmake --build build/ --target install
$ sudo ldconfig

1.3. Building the Paho C++ library

$ git clone https://github.com/eclipse/paho.mqtt.cpp
$ cd paho.mqtt.cpp

$ cmake -Bbuild -H. -DPAHO_BUILD_STATIC=ON \
    -DPAHO_BUILD_DOCUMENTATION=TRUE -DPAHO_BUILD_SAMPLES=TRUE
$ sudo cmake --build build/ --target install
$ sudo ldconfig

2. Linux C++ 发布端代码

#include <iostream>
#include <sstream>
#include "mqtt/async_client.h"
#include "mqtt/properties.h"

#include <chrono>

const string SERVER_ADDRESS { "tcp://127.0.0.1:1883" }; //tcp://172.17.0.1:1883
const auto TIMEOUT = std::chrono::seconds(10);

int main(int argc, char* argv[])
{
	if (argc < 2) {
		cout << "USAGE: rpc_math_cli <add|query|delete>" << endl;
		return 1;
	}

	constexpr int QOS = 1;
	const string REQ_TOPIC_HDR { "/mqttTopicName" };
	const string client_id = "zzzyc";
	mqtt::create_options createOpts(MQTTVERSION_5);
	mqtt::async_client cli(SERVER_ADDRESS, client_id, createOpts);

	auto connOpts = mqtt::connect_options_builder()
						.user_name("waytous")
						.password("1")
					    .mqtt_version(MQTTVERSION_5)
					    .clean_start()

						.finalize();

	cli.start_consuming();

	try {
		cout << "Connecting..." << flush;
		mqtt::token_ptr tok = cli.connect(connOpts);
		auto connRsp = tok->get_connect_response();
		cout << "OK (" << connRsp.get_server_uri() << ")" << endl;



		string repTopic = "replies/" + client_id + "/mqttTopicName";
		cout << "    Reply topic: " << repTopic << endl;

		// Subscribe to the reply topic and verify the QoS
		tok = cli.subscribe(repTopic, QOS);
		tok->wait();

		if (int(tok->get_reason_code()) != QOS) {
			cerr << "Error: Server doesn't support reply QoS: ["
				<< tok->get_reason_code() << "]" << endl;
			return 2;
		}

		// Create and send the request message

		string	req { argv[1] },
				reqTopic { REQ_TOPIC_HDR + req };

		mqtt::properties props {
			{ mqtt::property::RESPONSE_TOPIC, repTopic },
			{ mqtt::property::CORRELATION_DATA, "1" }
		};

         	string s = "MQTT Request Msg";

		string reqArgs { s};

		cout << "publish topic name: " << reqTopic << endl;
		cout << "\nSending request data: " << reqArgs << "..." << flush;
		auto pubmsg = mqtt::message_ptr_builder()
						  .topic(reqTopic)
						  .payload(reqArgs)
						  .qos(QOS)
						  .properties(props)
						  .finalize();

		cli.publish(pubmsg)->wait_for(TIMEOUT);
		cout << "OK" << endl;

		// Wait for reply.
		auto temp = updateDynamicHdmapLayer();
		if(s == temp)
		{
			cout <<"success"  << endl;
		}
		else
		{
			cout <<" failed"<<endl;
			cout << s << endl;
			cout << temp << endl;
		}

		auto msg = cli.try_consume_message_for(seconds(5));
		if (!msg) {
			cerr << "Didn't receive a reply from the service." << endl;
			return 1;
		}

		cout << "  Result: " << msg->to_string() << endl;

		// Unsubscribe
		cli.unsubscribe(repTopic)->wait();

		// Disconnect
		cout << "\nDisconnecting..." << flush;
		cli.disconnect()->wait();
		cout << "OK" << endl;
	}
	catch (const mqtt::exception& exc)
	 {
		cerr << exc.what() << endl;
		return 1;
	}

 	return 0;
}

3. Linux C++ 订阅端代码

#include <iostream>
#include <sstream>

#include "mqtt/client.h"

const std::string SERVER_ADDRESS { "tcp://127.0.0.1:1883" }; //todo: tcp://localhost:1883
const std::string CLIENT_ID	 { "rpc_math_srvr" };
constexpr auto RESPONSE_TOPIC	= mqtt::property::RESPONSE_TOPIC;
constexpr auto CORRELATION_DATA	= mqtt::property::CORRELATION_DATA;

bool try_reconnect(mqtt::client& cli)
{
  constexpr int N_ATTEMPT = 30;

  for (int i=0; i<N_ATTEMPT && !cli.is_connected(); ++i)
  {
    try
    {
      cli.reconnect();
      return true;
    }
    catch (const mqtt::exception&)
    {
      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  }
  return false;
}

int main(int argc, char* argv[])
{

  mqtt::create_options createOpts(MQTTVERSION_5);
  mqtt::client cli(SERVER_ADDRESS, client_id, createOpts);
  
  auto connOpts = mqtt::connect_options_builder()
      .mqtt_version(MQTTVERSION_5)
      .user_name("zyc")
      .password("1")
      .keep_alive_interval(std::chrono::seconds(20))
      .clean_start(true)
      .finalize();
      
  std::string topicNameOfMqttMsg = "/mqttTopicName";

  const std::vector<std::string> TOPICS { topicNameOfMqttMsg, topicNameOfMqttMsg + "/#" };
  const std::vector<int> QOS { 1, 1 };

  try
  {
    std::cout << str_busi_name << " : Connecting to the MQTT server(ReceiveMsg)... " << std::endl;

    do
    {
      try
      {
        auto result = cli.connect(connOpts);
        if (!cli.is_connected())
        {
          usleep(1000);
          std::cout << str_busi_name <<": re cli.connect()" << std::endl;
          continue;
        }
        break;
      }
      catch (const mqtt::exception& exc)
      {
        std::cerr << "[" << __LINE__ << "]" << str_busi_name << " : " << exc.what() << std::endl;
        usleep(1000); //tdo:
        continue;
      }
    }while(true);


    cli.subscribe(TOPICS, QOS);
    std::cout << str_busi_name <<" : OK \n" << std::endl;

    // Consume messages
    std::cout << str_busi_name <<" : Waiting for RPC requests..." << std::endl;

    while (true)
    {
      auto msg = cli.consume_message();

      if (!msg)
      {
        if (!cli.is_connected())
        {
          std::cout << str_busi_name <<" : Lost connection. Attempting reconnect" << std::endl;
          if (try_reconnect(cli))
          {
            cli.subscribe(TOPICS, QOS);
            std::cout << str_busi_name <<" : Reconnected" << std::endl;
            continue;
          }
          else
          {
            std::cout << str_busi_name <<" : Reconnect failed." << std::endl;
            break;
          }
        }
        else
          break;
      }

      std::cout << str_busi_name <<" : Received a request" << std::endl;

      const mqtt::properties& props = msg->get_properties();
      if(!props.contains(RESPONSE_TOPIC) || !props.contains(CORRELATION_DATA))
      {
        logger_main->error("[{0}][{1}][{2}] Error Request Msg: ", __CLASS__, __FUNCTION__ ,__LINE__);
        continue;
      }

      mqtt::binary corr_id  = mqtt::get<std::string>(props, CORRELATION_DATA);
      std::string reply_to = mqtt::get<std::string>(props, RESPONSE_TOPIC);

      std::cout << str_busi_name <<" : Client wants a reply to [" << corr_id << "] on '" << reply_to << "'" << std::endl;

      //std::cout << msg->get_topic() << ": " << msg->to_string() << std::endl;

      std::string str_response = "MQTT Reponse Msg. ";
      auto reply_msg = mqtt::message::create(reply_to, pqxx::to_string(str_response), 1, false);
      cli.publish(reply_msg);

      usleep(100); //tdo:

    }

    // Disconnect
    std::cout << str_busi_name <<" : Disconnecting from the MQTT server..." << std::endl;
    cli.disconnect();
    std::cout << str_busi_name <<" : OK" << std::endl;

  }
  catch (const mqtt::exception& exc)
  {
    //std::cerr << exc.what() << std::endl;
    std::cerr << "[" << __LINE__ << "]" << str_busi_name << " : " << exc.what() << std::endl;
    return 1;
  }

  return 0;
}


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adunn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值