Commit 2569446f0a0768735feea538f102642d27c69424
1 parent
8f48be6b
Added extra subscription checks to prevent double connections
Showing
9 changed files
with
202 additions
and
27 deletions
CMakeLists.txt
examples/sub/main.cpp
| ... | ... | @@ -27,6 +27,8 @@ |
| 27 | 27 | |
| 28 | 28 | #include "subscriber.h" |
| 29 | 29 | |
| 30 | +const int MAX_LOOP_COUNT = 10; | |
| 31 | + | |
| 30 | 32 | enum TIME_RES |
| 31 | 33 | { |
| 32 | 34 | T_MICRO, |
| ... | ... | @@ -65,6 +67,7 @@ void sleepcp( int number, TIME_RES resolution = T_MILLI ) // Cross-platform s |
| 65 | 67 | |
| 66 | 68 | int main( int argc, char* argv[] ) |
| 67 | 69 | { |
| 70 | + int loop_counter = 0; | |
| 68 | 71 | // Satisfy the compiler |
| 69 | 72 | (void)argc; |
| 70 | 73 | (void)argv; |
| ... | ... | @@ -79,14 +82,32 @@ int main( int argc, char* argv[] ) |
| 79 | 82 | pSubscriber->connect( "localhost", 1883, "", "", "test/subscriber/LWT", "Subscriber disconnected." ); |
| 80 | 83 | |
| 81 | 84 | std::cout << "Subscribing to the test-topic....." << std::endl; |
| 82 | - pSubscriber->subscribe( "test/publisher/#" ); | |
| 85 | + pSubscriber->subscribe( "test/publisher/TestPublisher_0" ); | |
| 86 | + pSubscriber->subscribe( "test/publisher/TestPublisher_1" ); | |
| 87 | + pSubscriber->subscribe( "test/publisher/TestPublisher_2" ); | |
| 88 | + pSubscriber->subscribe( "test/publisher/TestPublisher_3" ); | |
| 83 | 89 | |
| 84 | 90 | // Start a loop to give the subscriber the possibility to do its work. |
| 85 | - while( 1 ) | |
| 91 | + while (loop_counter < MAX_LOOP_COUNT) | |
| 86 | 92 | { |
| 87 | 93 | sleepcp( 1, T_SECONDS ); // Sleep 1 Sec to give the scheduler the change to interfene. |
| 88 | 94 | std::cout << "."; |
| 95 | + loop_counter++; | |
| 96 | + } | |
| 97 | + | |
| 98 | + std::cout << "Unsubscribing from test/publisher/#" << std::endl; | |
| 99 | + | |
| 100 | + pSubscriber->unsubscribe("test/publisher/#" ); | |
| 101 | + pSubscriber->unsubscribe( "test/publisher/TestPublisher_0" ); | |
| 102 | + pSubscriber->unsubscribe( "test/publisher/TestPublisher_1" ); | |
| 103 | + pSubscriber->unsubscribe( "test/publisher/TestPublisher_2" ); | |
| 104 | + | |
| 105 | + while (1) | |
| 106 | + { | |
| 107 | + sleepcp(1, T_MILLI); // Sleep 1 Sec to give the scheduler the change to interfene. | |
| 108 | + std::cout << "."; | |
| 89 | 109 | } |
| 110 | + | |
| 90 | 111 | } |
| 91 | 112 | else |
| 92 | 113 | { | ... | ... |
examples/sub/subscriber.cpp
| ... | ... | @@ -43,6 +43,11 @@ void Subscriber::subscribe( const std::string &message_topic ) |
| 43 | 43 | }); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | +void Subscriber::unsubscribe( const std::string &message_topic ) | |
| 47 | +{ | |
| 48 | + m_mqtt_client.unsubscribe( message_topic, 1 ); | |
| 49 | +} | |
| 50 | + | |
| 46 | 51 | void Subscriber::receive_data( const std::string &message_topic, const std::string &message_payload ) |
| 47 | 52 | { |
| 48 | 53 | std::cout << "[Subscriber::receive_data] - Received message : " << message_payload << " from topic : " << message_topic << std::endl; | ... | ... |
examples/sub/subscriber.h
examples/subunsub/CMakeLists.txt
0 → 100644
| 1 | +cmake_minimum_required(VERSION 3.0) | |
| 2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake) | |
| 3 | + | |
| 4 | +include(projectheader) | |
| 5 | +project_header(test_subunsub) | |
| 6 | + | |
| 7 | +include_directories( SYSTEM | |
| 8 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../include | |
| 9 | +) | |
| 10 | + | |
| 11 | +include(compiler) | |
| 12 | +set(SRC_LIST | |
| 13 | + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp | |
| 14 | +) | |
| 15 | + | |
| 16 | +add_executable( ${PROJECT_NAME} | |
| 17 | + ${SRC_LIST} | |
| 18 | +) | |
| 19 | + | |
| 20 | +target_link_libraries( | |
| 21 | + ${PROJECT_NAME} | |
| 22 | + mqtt-cpp | |
| 23 | +) | |
| 24 | + | |
| 25 | +set_target_properties( ${PROJECT_NAME} PROPERTIES | |
| 26 | + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin | |
| 27 | + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib | |
| 28 | + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib | |
| 29 | +) | |
| 30 | + | |
| 31 | +include(installation) | |
| 32 | +install_application() | ... | ... |
examples/subunsub/main.cpp
0 → 100644
| 1 | +#include <iostream> | |
| 2 | +#include <string> | |
| 3 | +#include <vector> | |
| 4 | + | |
| 5 | +#include "mqttclient.h" | |
| 6 | + | |
| 7 | +using namespace osdev::components::mqtt; | |
| 8 | + | |
| 9 | +std::vector<std::string> vecTopics = | |
| 10 | +{ | |
| 11 | + "test/publisher/TestPublisher_0", | |
| 12 | + "test/publisher/TestPublisher_1", | |
| 13 | + "test/publisher/TestPublisher_2", | |
| 14 | + "test/publisher/TestPublisher_3", | |
| 15 | + "test/publisher/TestPublisher_4", | |
| 16 | + "test/publisher/TestPublisher_5", | |
| 17 | + "test/publisher/TestPublisher_6", | |
| 18 | + "test/publisher/TestPublisher_7", | |
| 19 | + "test/publisher/TestPublisher_8", | |
| 20 | + "test/publisher/TestPublisher_9", | |
| 21 | +}; | |
| 22 | + | |
| 23 | +MqttClient oClient("SubscriptionTest"); | |
| 24 | + | |
| 25 | +enum TIME_RES | |
| 26 | +{ | |
| 27 | + T_MICRO, | |
| 28 | + T_MILLI, | |
| 29 | + T_SECONDS | |
| 30 | +}; | |
| 31 | + | |
| 32 | +std::uint64_t getEpochUSecs() | |
| 33 | +{ | |
| 34 | + auto tsUSec = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()); | |
| 35 | + return static_cast<std::uint64_t>(tsUSec.time_since_epoch().count()); | |
| 36 | +} | |
| 37 | + | |
| 38 | +void sleepcp( int number, TIME_RES resolution = T_MILLI ) // Cross-platform sleep function | |
| 39 | +{ | |
| 40 | + int factor = 0; // Should not happen.. | |
| 41 | + | |
| 42 | + switch( resolution ) | |
| 43 | + { | |
| 44 | + case T_MICRO: | |
| 45 | + factor = 1; | |
| 46 | + break; | |
| 47 | + | |
| 48 | + case T_MILLI: | |
| 49 | + factor = 1000; | |
| 50 | + break; | |
| 51 | + | |
| 52 | + case T_SECONDS: | |
| 53 | + factor = 1000000; | |
| 54 | + break; | |
| 55 | + } | |
| 56 | + | |
| 57 | + usleep( number * factor ); | |
| 58 | +} | |
| 59 | + | |
| 60 | +void Subscribe() | |
| 61 | +{ | |
| 62 | + for( const auto &message_topic : vecTopics) | |
| 63 | + { | |
| 64 | + std::cout << "Subscribing to : " << message_topic << std::endl; | |
| 65 | + oClient.subscribe(message_topic, 1, [](const osdev::components::mqtt::MqttMessage &message) | |
| 66 | + { | |
| 67 | + std::cout << "Received Topic : [" << message.topic() << "] Payload : " << message.payload() << std::endl; | |
| 68 | + }); | |
| 69 | + } | |
| 70 | +} | |
| 71 | + | |
| 72 | +void Unsubscribe() | |
| 73 | +{ | |
| 74 | + for( const auto &message_topic : vecTopics) | |
| 75 | + { | |
| 76 | + std::cout << "Unsubscribing from : " << message_topic << std::endl; | |
| 77 | + oClient.unsubscribe(message_topic, 1); | |
| 78 | + } | |
| 79 | +} | |
| 80 | + | |
| 81 | +int main(int argc, char* argv[]) | |
| 82 | +{ | |
| 83 | + (void)argc; | |
| 84 | + (void)argv; | |
| 85 | + | |
| 86 | + oClient.connect("localhost", 1883, Credentials()); | |
| 87 | + | |
| 88 | + // First create all subscriptions | |
| 89 | + Subscribe(); | |
| 90 | + sleepcp(1, T_SECONDS); | |
| 91 | + | |
| 92 | + while(1) | |
| 93 | + { | |
| 94 | + Unsubscribe(); | |
| 95 | + sleepcp(1, T_SECONDS); | |
| 96 | + Subscribe(); | |
| 97 | + sleepcp(10, T_SECONDS); | |
| 98 | + } | |
| 99 | + | |
| 100 | +} | ... | ... |
src/CMakeLists.txt
| ... | ... | @@ -15,31 +15,31 @@ include_directories( |
| 15 | 15 | set(SRC_LIST |
| 16 | 16 | ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp |
| 17 | 17 | ${CMAKE_CURRENT_SOURCE_DIR}/threadcontext.cpp |
| 18 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttpublisherbase.cpp | |
| 19 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttsubscriberbase.cpp | |
| 20 | - ${CMAKE_CURRENT_SOURCE_DIR}/clientpaho.cpp | |
| 21 | - ${CMAKE_CURRENT_SOURCE_DIR}/commondefs.cpp | |
| 22 | - ${CMAKE_CURRENT_SOURCE_DIR}/connectionstatus.cpp | |
| 23 | - ${CMAKE_CURRENT_SOURCE_DIR}/credentials.cpp | |
| 24 | - ${CMAKE_CURRENT_SOURCE_DIR}/errorcode.cpp | |
| 25 | - ${CMAKE_CURRENT_SOURCE_DIR}/token.cpp | |
| 26 | - ${CMAKE_CURRENT_SOURCE_DIR}/ihistogram.cpp | |
| 27 | - ${CMAKE_CURRENT_SOURCE_DIR}/timemeasurement.cpp | |
| 28 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttidgenerator.cpp | |
| 29 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqtttypeconverter.cpp | |
| 30 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttutil.cpp | |
| 31 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttmessage.cpp | |
| 32 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttclient.cpp | |
| 33 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttfailure.cpp | |
| 34 | - ${CMAKE_CURRENT_SOURCE_DIR}/mqttsuccess.cpp | |
| 35 | - ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp | |
| 36 | - ${CMAKE_CURRENT_SOURCE_DIR}/imqttclientimpl.cpp | |
| 37 | - ${CMAKE_CURRENT_SOURCE_DIR}/istatecallback.cpp | |
| 38 | - ${CMAKE_CURRENT_SOURCE_DIR}/scopeguard.cpp | |
| 39 | - ${CMAKE_CURRENT_SOURCE_DIR}/serverstate.cpp | |
| 40 | - ${CMAKE_CURRENT_SOURCE_DIR}/sharedreaderlock.cpp | |
| 41 | - ${CMAKE_CURRENT_SOURCE_DIR}/stringutils.cpp | |
| 42 | - ${CMAKE_CURRENT_SOURCE_DIR}/uriparser.cpp | |
| 18 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttpublisherbase.cpp | |
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttsubscriberbase.cpp | |
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/clientpaho.cpp | |
| 21 | + ${CMAKE_CURRENT_SOURCE_DIR}/commondefs.cpp | |
| 22 | + ${CMAKE_CURRENT_SOURCE_DIR}/connectionstatus.cpp | |
| 23 | + ${CMAKE_CURRENT_SOURCE_DIR}/credentials.cpp | |
| 24 | + ${CMAKE_CURRENT_SOURCE_DIR}/errorcode.cpp | |
| 25 | + ${CMAKE_CURRENT_SOURCE_DIR}/token.cpp | |
| 26 | + ${CMAKE_CURRENT_SOURCE_DIR}/ihistogram.cpp | |
| 27 | + ${CMAKE_CURRENT_SOURCE_DIR}/timemeasurement.cpp | |
| 28 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttidgenerator.cpp | |
| 29 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqtttypeconverter.cpp | |
| 30 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttutil.cpp | |
| 31 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttmessage.cpp | |
| 32 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttclient.cpp | |
| 33 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttfailure.cpp | |
| 34 | + ${CMAKE_CURRENT_SOURCE_DIR}/mqttsuccess.cpp | |
| 35 | + ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp | |
| 36 | + ${CMAKE_CURRENT_SOURCE_DIR}/imqttclientimpl.cpp | |
| 37 | + ${CMAKE_CURRENT_SOURCE_DIR}/istatecallback.cpp | |
| 38 | + ${CMAKE_CURRENT_SOURCE_DIR}/scopeguard.cpp | |
| 39 | + ${CMAKE_CURRENT_SOURCE_DIR}/serverstate.cpp | |
| 40 | + ${CMAKE_CURRENT_SOURCE_DIR}/sharedreaderlock.cpp | |
| 41 | + ${CMAKE_CURRENT_SOURCE_DIR}/stringutils.cpp | |
| 42 | + ${CMAKE_CURRENT_SOURCE_DIR}/uriparser.cpp | |
| 43 | 43 | ) |
| 44 | 44 | |
| 45 | 45 | include(library) | ... | ... |
src/clientpaho.cpp
| ... | ... | @@ -515,6 +515,19 @@ std::int32_t ClientPaho::unsubscribe( const std::string& topic, int qos ) |
| 515 | 515 | break; |
| 516 | 516 | } |
| 517 | 517 | } |
| 518 | + | |
| 519 | + if(!found) // Probably not found in subscriptions, also check the pendings. | |
| 520 | + { | |
| 521 | + for( const auto &s : m_pendingSubscriptions ) | |
| 522 | + { | |
| 523 | + if( topic == s.first && qos == s.second.qos ) | |
| 524 | + { | |
| 525 | + found = true; | |
| 526 | + break; | |
| 527 | + } | |
| 528 | + } | |
| 529 | + } | |
| 530 | + | |
| 518 | 531 | if( !found ) |
| 519 | 532 | { |
| 520 | 533 | return -1; | ... | ... |
src/mqttclient.cpp
| ... | ... | @@ -313,6 +313,7 @@ std::set<Token> MqttClient::unsubscribe(const std::string& topic, int qos) |
| 313 | 313 | // Throw (MqttException, "Not connected"); |
| 314 | 314 | return std::set<Token>(); |
| 315 | 315 | } |
| 316 | + | |
| 316 | 317 | clients.push_back(m_principalClient.get()); |
| 317 | 318 | for (const auto& c : m_additionalClients) |
| 318 | 319 | { | ... | ... |