Get a list of connected client IDs from MQTT client
Asked Answered
F

7

16

As a mqtt client connected to mosquitto is it possible to retrieve a list of client IDs who are also connected to the broker?

Forevermore answered 19/3, 2012 at 8:34 Comment(0)
H
8

method I: handle in client logic

as @user1048839 says, use client's LWT & online publish msg, maintain client status on a custom topic. subscript this topic & maintain client list self.

if pub retain msg, once sub will get the client list.

method II: change mosquitto broker code

official code not support online_list,
so I patched mosquitto 1.5.4, add 2 custom sys topic:

1. online list

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_list'
$SYS/broker/chen_list
0 - CLOUD0_19108
1 - EEE
2 - DDD

2. online/offline event

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_state/#'
$SYS/broker/chen_state/DDD 1
$SYS/broker/chen_state/EEE 1
$SYS/broker/chen_state/CLOUD0_19108 1
$SYS/broker/chen_state/EEE 0
$SYS/broker/chen_state/EEE 1

// if pub retain msg, sub this topic can get all clients online state (in payload).

test source code on github:

4-online-list

5-online-event

Hateful answered 19/12, 2018 at 23:41 Comment(2)
How to download the exe on windows? I don't know how to build, I just want to use it.Exotoxin
@Exotoxin sorry, I didn't build on windows, as readme.md says, use cmake to build on windowsHateful
A
10

one way to implement this is let the client publish a message with topic "status/client-id" and payload "1" every time when it connects the broker, and with payload "0" when it disconnects.

Then on the server(broker) side, setup another client subscribe to the topic "status/#", when it gets any message like this, store the client-id and payload(connected or not) into database.

then you can read the database to know exactly which client is online or offline.

Ashjian answered 12/3, 2013 at 5:53 Comment(3)
if you would read you would know I just figured this out before a year myself ;)Forevermore
good to know. do you find a better/more efficient way to do it? :) just want to learnAshjian
better to just use LWT instead of expecting the client to publish a message on disconnect.Gobble
H
8

method I: handle in client logic

as @user1048839 says, use client's LWT & online publish msg, maintain client status on a custom topic. subscript this topic & maintain client list self.

if pub retain msg, once sub will get the client list.

method II: change mosquitto broker code

official code not support online_list,
so I patched mosquitto 1.5.4, add 2 custom sys topic:

1. online list

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_list'
$SYS/broker/chen_list
0 - CLOUD0_19108
1 - EEE
2 - DDD

2. online/offline event

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_state/#'
$SYS/broker/chen_state/DDD 1
$SYS/broker/chen_state/EEE 1
$SYS/broker/chen_state/CLOUD0_19108 1
$SYS/broker/chen_state/EEE 0
$SYS/broker/chen_state/EEE 1

// if pub retain msg, sub this topic can get all clients online state (in payload).

test source code on github:

4-online-list

5-online-event

Hateful answered 19/12, 2018 at 23:41 Comment(2)
How to download the exe on windows? I don't know how to build, I just want to use it.Exotoxin
@Exotoxin sorry, I didn't build on windows, as readme.md says, use cmake to build on windowsHateful
B
6

You could presumably get this information via the BASH commands netstat, grep and if necessary awk. If Mosquitto is using port 1883 then the following will tell you what you want:

sudo netstat -n | grep :1883
Benzol answered 22/9, 2016 at 4:55 Comment(2)
That implies that there is only one client per remote IP and doesn't actually give you the clientidPlastometer
This is more reliable (if you have mqtt in your /etc/services): sudo netstat -n | grep :1883Odoacer
F
2

No.

It might be better discussing this on the mosquitto mailing list: https://launchpad.net/~mqtt-users

Fabiolafabiolas answered 19/3, 2012 at 19:31 Comment(0)
F
2

well, I now created a workaround using a PHP script: it starts the mosquitto broker, reads the output, and if someone connects or disconnects it sends an XML string with the connected clients to the broker. (the posted code is a bit simplified as I additionally query a database for more information about the user)

<?php 
    require ('SAM/php_sam.php');
    if (!$handle = popen('mosquitto 2>&1', 'r')) {
        die('could not start mosquitto');
    }
    function usersToXML($users) {
        $xml = '<?xml version="1.0"?><userlist>';
        foreach ($users as $user) {
            $xml.= '<user>' . '<id><![CDATA[' . $user->id . ']]></id>' . '</user>';
        }
        $xml.= '</userlist>';
        return $xml;
    }
    function updateBroadcast($users) {
        sleep(1);
        ob_start();
        $conn = new SAMConnection();
        $conn->Connect(SAM_MQTT, array(SAM_HOST => '127.0.0.1', SAM_PORT => 1883));
        $conn->Send('topic://broadcast', (object)array('body' => usersToXML($users)));
        $conn->Disconnect();
        ob_end_clean();
    }
    while ($line = fread($handle, 2096)) {
        echo $line;
        if (preg_match('/New client connected from .+ as user_(\d+)./', $line, $regs)) {
            $user = (object)array('id' => $regs[1]);
            $connectedUsers[$user->id] = $user;
            updateBroadcast($connectedUsers);
        } else if (preg_match('/Received DISCONNECT from user_(\d+)/', $line, $regs) || preg_match('/Client user_(\d+) has exceeded timeout, disconnecting./', $line, $regs) || preg_match('/Socket read error on client user_(\d+), disconnecting./', $line, $regs)) {
            if (isset($connectedUsers[$regs[1]])) {
                unset($connectedUsers[$regs[1]]);
                updateBroadcast($connectedUsers);
            }
        }
    }
    pclose($handle);
?>
Forevermore answered 20/3, 2012 at 13:53 Comment(1)
very much similar with mine. i used another client to just to manage the "status/client-id" topic.Ashjian
B
2

A good work-around for this is to have the clients(if possible) define a Last will and testament(LWT). Your server will subscribe to a special topic where the LWT will be published to and assume all clients as online unless they publish to that topic.

MQTT what is the purpose or usage of Last Will Testament?

Broaddus answered 6/9, 2014 at 10:31 Comment(0)
D
1

You can get list of online/connected client from mosquitto.log file on server if you access it.

  1. Read last line that added to the log file and process it with regex to access to deviceID.
const Tail = require('tail-file');

const mosquittoLogFilePath = '/var/log/mosquitto/mosquitto.log';
const mytail = new Tail(mosquittoLogFilePath, line => {
  if (line.includes("PINGRESP")){
      const deviceId = translatePingResponse(line);
      if(deviceId){
        processOnlineClient(deviceId);
      }
  }
});

  1. Translate with regex
function translatePingResponse(line){
    const regex = /\w* Sending PINGRESP to (\w*-\w*-\w*-\w*-\w*)/g;
    const found = [...line.matchAll(regex)];
    if(
      found[0] &&
      found[0][1]
    ){
      const manufactureId = found[0][1];
      return manufactureId;
    }else{
      console.log(`unknown line -> ${line}`);
    }
  
}
  1. Do the process
function processOnlineClient(deviceId){
    console.log(`${deviceId} is Online`);
}

See this repo that I created 📦 msqtConnectedClinets in nodeJS.

Dorcy answered 21/8, 2022 at 8:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.