sync_publish.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // sync_publish.cpp
  2. //
  3. // This is a Paho MQTT C++ client, sample application.
  4. //
  5. // It's an example of how to send messages as an MQTT publisher using the
  6. // C++ synchronous client interface.
  7. //
  8. // The sample demonstrates:
  9. // - Connecting to an MQTT server/broker
  10. // - Publishing messages
  11. // - User-defined persistence
  12. //
  13. /*******************************************************************************
  14. * Copyright (c) 2013-2017 Frank Pagliughi <fpagliughi@mindspring.com>
  15. *
  16. * All rights reserved. This program and the accompanying materials
  17. * are made available under the terms of the Eclipse Public License v1.0
  18. * and Eclipse Distribution License v1.0 which accompany this distribution.
  19. *
  20. * The Eclipse Public License is available at
  21. * http://www.eclipse.org/legal/epl-v10.html
  22. * and the Eclipse Distribution License is available at
  23. * http://www.eclipse.org/org/documents/edl-v10.php.
  24. *
  25. * Contributors:
  26. * Frank Pagliughi - initial implementation and documentation
  27. *******************************************************************************/
  28. #include <iostream>
  29. #include <cstdlib>
  30. #include <string>
  31. #include <map>
  32. #include <vector>
  33. #include <cstring>
  34. #include "mqtt/client.h"
  35. const std::string SERVER_ADDRESS { "tcp://localhost:1883" };
  36. const std::string CLIENT_ID { "sync_publish_cpp" };
  37. const std::string TOPIC { "hello" };
  38. const std::string PAYLOAD1 { "Hello World!" };
  39. const char* PAYLOAD2 = "Hi there!";
  40. const char* PAYLOAD3 = "Is anyone listening?";
  41. const int QOS = 1;
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Example of a simple, in-memory persistence class.
  44. class sample_mem_persistence : virtual public mqtt::iclient_persistence
  45. {
  46. // Whether the store is open
  47. bool open_;
  48. // Use an STL map to store shared persistence pointers
  49. // against string keys.
  50. std::map<std::string, std::string> store_;
  51. public:
  52. sample_mem_persistence() : open_(false) {}
  53. // "Open" the store
  54. void open(const std::string& clientId, const std::string& serverURI) override {
  55. std::cout << "[Opening persistence store for '" << clientId
  56. << "' at '" << serverURI << "']" << std::endl;
  57. open_ = true;
  58. }
  59. // Close the persistent store that was previously opened.
  60. void close() override {
  61. std::cout << "[Closing persistence store.]" << std::endl;
  62. open_ = false;
  63. }
  64. // Clears persistence, so that it no longer contains any persisted data.
  65. void clear() override {
  66. std::cout << "[Clearing persistence store.]" << std::endl;
  67. store_.clear();
  68. }
  69. // Returns whether or not data is persisted using the specified key.
  70. bool contains_key(const std::string &key) override {
  71. return store_.find(key) != store_.end();
  72. }
  73. // Returns the keys in this persistent data store.
  74. const mqtt::string_collection& keys() const override {
  75. static mqtt::string_collection ks;
  76. ks.clear();
  77. for (const auto& k : store_)
  78. ks.push_back(k.first);
  79. return ks;
  80. }
  81. // Puts the specified data into the persistent store.
  82. void put(const std::string& key, const std::vector<mqtt::string_view>& bufs) override {
  83. std::cout << "[Persisting data with key '"
  84. << key << "']" << std::endl;
  85. std::string str;
  86. for (const auto& b : bufs)
  87. str += b.str();
  88. store_[key] = std::move(str);
  89. }
  90. // Gets the specified data out of the persistent store.
  91. mqtt::string_view get(const std::string& key) const override {
  92. std::cout << "[Searching persistence for key '"
  93. << key << "']" << std::endl;
  94. auto p = store_.find(key);
  95. if (p == store_.end())
  96. throw mqtt::persistence_exception();
  97. std::cout << "[Found persistence data for key '"
  98. << key << "']" << std::endl;
  99. return mqtt::string_view(p->second);
  100. }
  101. // Remove the data for the specified key.
  102. void remove(const std::string &key) override {
  103. std::cout << "[Persistence removing key '" << key << "']" << std::endl;
  104. auto p = store_.find(key);
  105. if (p == store_.end())
  106. throw mqtt::persistence_exception();
  107. store_.erase(p);
  108. std::cout << "[Persistence key removed '" << key << "']" << std::endl;
  109. }
  110. };
  111. /////////////////////////////////////////////////////////////////////////////
  112. // Class to receive callbacks
  113. class user_callback : public virtual mqtt::callback
  114. {
  115. void connection_lost(const std::string& cause) override {
  116. std::cout << "\nConnection lost" << std::endl;
  117. if (!cause.empty())
  118. std::cout << "\tcause: " << cause << std::endl;
  119. }
  120. void delivery_complete(mqtt::delivery_token_ptr tok) override {
  121. std::cout << "\n\t[Delivery complete for token: "
  122. << (tok ? tok->get_message_id() : -1) << "]" << std::endl;
  123. }
  124. public:
  125. };
  126. // --------------------------------------------------------------------------
  127. int main(int argc, char* argv[])
  128. {
  129. std::cout << "Initialzing..." << std::endl;
  130. sample_mem_persistence persist;
  131. mqtt::client client(SERVER_ADDRESS, CLIENT_ID, &persist);
  132. user_callback cb;
  133. client.set_callback(cb);
  134. mqtt::connect_options connOpts;
  135. connOpts.set_keep_alive_interval(20);
  136. connOpts.set_clean_session(true);
  137. std::cout << "...OK" << std::endl;
  138. try {
  139. std::cout << "\nConnecting..." << std::endl;
  140. client.connect(connOpts);
  141. std::cout << "...OK" << std::endl;
  142. // First use a message pointer.
  143. std::cout << "\nSending message..." << std::endl;
  144. auto pubmsg = mqtt::make_message(TOPIC, PAYLOAD1);
  145. pubmsg->set_qos(QOS);
  146. client.publish(pubmsg);
  147. std::cout << "...OK" << std::endl;
  148. // Now try with itemized publish.
  149. std::cout << "\nSending next message..." << std::endl;
  150. client.publish(TOPIC, PAYLOAD2, strlen(PAYLOAD2)+1);
  151. std::cout << "...OK" << std::endl;
  152. // Now try with a listener, no token, and non-heap message
  153. std::cout << "\nSending final message..." << std::endl;
  154. client.publish(mqtt::message(TOPIC, PAYLOAD3, QOS, false));
  155. std::cout << "OK" << std::endl;
  156. // Disconnect
  157. std::cout << "\nDisconnecting..." << std::endl;
  158. client.disconnect();
  159. std::cout << "...OK" << std::endl;
  160. }
  161. catch (const mqtt::persistence_exception& exc) {
  162. std::cerr << "Persistence Error: " << exc.what() << " ["
  163. << exc.get_reason_code() << "]" << std::endl;
  164. return 1;
  165. }
  166. catch (const mqtt::exception& exc) {
  167. std::cerr << exc.what() << std::endl;
  168. return 1;
  169. }
  170. std::cout << "\nExiting" << std::endl;
  171. return 0;
  172. }