Topic and message not printed why?

extern crate mosquitto_client as mosq;
extern crate rustc_serialize;
use rustc_serialize::json::Json;
use std::fs::File;
use std::io::Read;
use mosq::Mosquitto;
use std::thread;
use ini::Ini;
use serde_json::json;
use std::{collections::HashMap, sync::Mutex}; 
use std::time::{SystemTime, UNIX_EPOCH};
use std::path::Path;

fn on_connect() -> mosq::Mosquitto {
    let m = Mosquitto::new("test");
    m.connect("broker.hivemq.com",1883).expect("can't connect");
    m
}

fn on_message(m: & mosq::Mosquitto) {
    let mut mc = m.callbacks(());
    mc.on_message(|_,msg| {
        println!("message recieved= {}",msg.text());
        println!("message topic= {}", msg.topic());
        println!("message qos= {}", msg.qos());
        println!("message retain flag= {}\n", msg.retained());
    });
    
    m.loop_forever(200).expect("broken loop");
}

fn hi() {
    let m = on_connect();
    m.publish("gui/aim", "hi".as_bytes(), 1, false).unwrap();
}

fn main() {
    let m = on_connect();
    
    m.subscribe("gui/aim",0).expect("can't subscribe to gui");
    /*m.subscribe("hi/asas",0).expect("can't subscribe to gui");*/
    
    /*let mut send_get_lasers_msg_dict = json!({
        "type": "device",
        "data": {
            "device": "lasers",
            "command": "get",
        }
    });*/
    
    /*let send_get_lasers_msg = send_get_lasers_msg_dict.to_string();*/      
    hi();
    on_message(&m);
        
    /*m.publish("gui/aim", "hi".as_bytes(), 1, false).unwrap();*/
    /*m.publish("hi/asas", "hi".as_bytes(), 1, false).unwrap();*/
}

Link to mqtt library: https://github.com/stevedonovan/mosquitto-client

Hi

Why do I not get the topic and message printed out when I have a m.publish() else where instead of inside the same function as m.subscribe(). How can I fix this so that m.publish() and m.subscribe() does not need to be in the same function?

Thanks

I believe the problem is that you create two Mosquitto clients with the same name. The docs for Mosquitto::new say, "Clients connecting to a broker must have unique names."

The program works if I make hi either take a reference to the client created in main, or have it create a client with a different name, like this:

fn on_connect(name: &str) -> mosq::Mosquitto {
    let m = Mosquitto::new(name);
    m.connect("broker.hivemq.com",1883).expect("can't connect");
    m
}

fn hi() {
    let m = on_connect("test2");
    m.publish("gui/aim", "hi".as_bytes(), 1, false).unwrap();
}

fn main() {
    let m = on_connect("test");    
    m.subscribe("gui/aim", 0).expect("can't subscribe to gui");    
    hi();
    on_message(&m);
}

How can I create an on_message function so that when there is a m.publish and m.subscribe for the same topic the topic, message, qos and retained is printed automatically without having to call on_message function explicitly.

I don't see any way to create an "on_message" callback without calling Callbacks::on_message. If you want to print something whenever a message arrives, calling on_message is the correct way to do it. However, you should only need to call it once; you don't need to call it for every message.

Also, speaking as a moderator of this forum: Please don't post the same reply repeatedly, and please take more effort to write detailed questions describing what you are trying and why, and exactly what problems you are running into. If someone offers possible solutions, please take the time to try them and explain why they do or don't work.

1 Like

What do you mean when you say on_message only needs to be called once. At the moment is all I know is on_message needs to be called when there is a subscribe and publish in the same function.

Your on_message is registering a callback function with the mosq library. You aren't responsible for invoking the callback, the mosq library is. (Presumably, it does this whenever it determines that a message has been received.) You just have to arrange for a message to be sent to (and processed by) the mosq library. How to do that is probably documented somewhere in that library.

How can I fix this so that m.publish() and m.subscribe() does not need to be in the same function?

You need to learn about how functions handle state. You can read about this anywhere, but the Rust book has a section on common programming concepts. Any data you create in a function is destroyed at the end of that function's scope unless you pass it to something else. You seem to be treating function calls as though their variables are all globally scoped, and that's not only a serious misunderstanding, it is not going to serve you at all if you're trying to write asynchronous event-handling code.

Until you understand the basics of the programming environment, it won't do any good to tell you how to fix this: you'll fix it and then immediately encounter an endless stream of nearly identical problems. Start with something simpler and build up an understanding of how these things work.

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.