moscajs / mosca

MQTT broker as a module
mosca.io
3.2k stars 513 forks source link

Problem with offline clients getting messages #671

Closed scramble45 closed 6 years ago

scramble45 commented 6 years ago

mosca@2.5.2 running w/ Redis - Clients using mqtt.js

webclient : http://www.hivemq.com/demos/websocket-client/js/mqttws31.js

Problem: When I subscribe and publish a message over websockets to mosca it's received by the listening client that's subscribed to those topics. However if the client is offline the message is never received when they come back online and subscribe again to those topics.

How id like this to work: a webclient connects over websockets to mosca and a message goes out on a specific topic this message should go out to all clients that are subscribed to this topic. But if a client is offline and they reconnect to those topics I want to make sure they got the last message that we sent out.

I am using the following in mosca for options:

/*********************************************************
* Mosca
**********************************************************/

var dbSettings = {
  type: 'redis',
  redis: require('redis'),
  db: 12,
  port: 6379,
  return_buffers: true, // to handle binary payloads
  host: "localhost"
};

var serverSettings = {
  port: 1883,                  //default port is 1883 for mqtt
  backend: dbSettings,         //database sttings we have created earlier
  http: {
  port: 3000,
  bundle: true,
  static: './public',
  stats: true
  },
  persistence: {
        factory: mosca.persistence.Redis,
        host: 'localhost',
        port: 6379,
        db: 2
  }
}

var server = new mosca.Server(serverSettings);
mcollina commented 6 years ago

Are you using QoS 1, clean=false and unique clientId?

scramble45 commented 6 years ago

Yes QoS 1 and clean = false and a unique clientId for each client.

The listening clients:

var client_Id = 'bloop_' + Math.random().toString(16).substr(2, 8);

var options = {
    keepalive: 10,
    clientId: client_Id,
    protocolId: 'MQTT',
    protocolVersion: 4,
    clean: false, // set to false to receive QoS 1 and 2 messages while offline
    reconnectPeriod: 1000,
    connectTimeout: 30 * 1000,
    will: { // in case of any abnormal client close this message will be fired
        topic: 'ErrorMsg',
        payload: 'Connection was closed abnormally..!',
        qos: 1,
        retain: true
    },
    username: 'mqtt_client',
    password: 'somepassword',
    rejectUnauthorized: true, // message should be authorized
    resubscribe: true // if connection is broken and reconnects, subscribed topics are automatically subscribed again

var client = mqtt.connect('mqtt://255.255.255.255:1883', options);
}

From the web client over websockets to mosca:

client.subscribe('topic/sometopic/cmd', {qos: 1}); // subscribe to the command channel
        var msgout = {meid:dockSNIn, cmd: cmdIn};
        publish(msgout, 'topic/sometopic/cmd', 1);

var publish = function (payload, topic, qos) {
    // pre stringify our JSON object
    payload = JSON.stringify(payload);
    var message = new Messaging.Message(payload);
    message.destinationName = topic;
    message.qos = qos;
    client.send(message);
}

Mosca:

/*********************************************************
* Mosca
**********************************************************/

var dbSettings = {
  type: 'redis',
  redis: require('redis'),
  db: 12,
  port: 6379,
  return_buffers: true,
  host: "localhost"
};

var serverSettings = {
  port: 1883,
  backend: dbSettings,
  http: {
  port: 3000,
  bundle: true,
  static: './public',
  stats: true
  },
  persistence: {
        factory: mosca.persistence.Redis,
        host: 'localhost',
        port: 6379,
        db: 2
  }
}
scramble45 commented 6 years ago

@mcollina may I get some clarification, suggestions on this issue please?

scramble45 commented 6 years ago

So I guess I wasn't passing:

retained: true

in the webclient. The offline client now gets the message.