Perl Modul Net::MQTT::Simple

LoxBerry Compatibility

This module is available starting with LoxBerry 1.4.1. If you use this module, set your lb_minimum version in your plugin.cfg.

Customized LoxBerry Module

This module is based on the original module Net::MQTT::Simple, but is an especially customized version for LoxBerry regarding to MQTT authentication and TLS support. For authentication, read the documentation in this wiki article. (thanks to Juerd, who implemented the enhancements on our demand).

The Net::MQTT::Simple library is an easy way to connect to an MQTT broker. 

In your plugin user interface, you need to allow users to configure the MQTT broker hostname/address and broker port, the username and the password. You should require LoxBerry's SecurePIN before transferring and displaying the broker credentials.

It is recommended to eval { }; the mqtt method calls to implement error handling on connection, authentication or subscription errors.

If you want it more easy and avoid to scamble around with broker address, broker port and credentials, you may try the MQTT Gateway - HTTP- und UDP-Interface (requires the MQTT Gateway plugin to be installed).

Publishing only

Use this example code, to connect only for publishing messages (with or without retain).

use Net::MQTT::Simple;
 
# Allow unencrypted connection with credentials
$ENV{MQTT_SIMPLE_ALLOW_INSECURE_LOGIN} = 1;
 
# Connect to broker
my $mqtt = Net::MQTT::Simple->new('localhost:1883');
 
# Depending if authentication is required, login to the broker
if($mqtt_username and $mqtt_password) {
    $mqtt->login($mqtt_username, $mqtt_password);
}
 
# Publish a message
$mqtt->publish("loxberry/myplugin/temperature", "26.5");
 
# Publish a message with retain flag
$mqtt->retain("loxberry/myplugin/temperature", "26.5");
 
$mqtt->disconnect();

Subscribe and listen to topics

Only wait for messages (blocking)

This example subscribes to a topic, and then only waits for a message to arrive. It is blocking.

use Net::MQTT::Simple;
 
# Allow unencrypted connection with credentials
$ENV{MQTT_SIMPLE_ALLOW_INSECURE_LOGIN} = 1;
 
# Connect to broker
my $mqtt = Net::MQTT::Simple->new('localhost:1883');
 
# Depending if authentication is required, login to the broker
if($mqtt_username and $mqtt_password) {
    $mqtt->login($mqtt_username, $mqtt_password);
}
 
$mqtt->subscribe("loxberry/myplugin/command", \&received);
 
# This call blocks, and runs the callback, when a message arrives
$mqtt->run();
 
$mqtt->disconnect();
 
# This is the callback function, when a message arrives for the subscribed topic
sub received 
{
    my ($topic, $message) = @_;
    print STDERR "Incoming message on topic $topic is: $message\n";
}

Non-blocking subscriptions

With this example, the method →tick is called, that checks for message. Inside of a loop, you can do other stuff in between.

use Net::MQTT::Simple;
 
# Allow unencrypted connection with credentials
$ENV{MQTT_SIMPLE_ALLOW_INSECURE_LOGIN} = 1;
 
# Connect to broker
my $mqtt = Net::MQTT::Simple->new('localhost:1883');
 
# Depending if authentication is required, login to the broker
if($mqtt_username and $mqtt_password) {
    $mqtt->login($mqtt_username, $mqtt_password);
}
 
$mqtt->subscribe("loxberry/myplugin/command", \&received);
 
while(1) {
    $mqtt->tick();
 
    # Now do other stuff
    sleep(1);
 
    # For fast response, use
    use Time::HiRes;
    Time::Hires::sleep(50/1000); # 50/1000 = 50ms
}
 
$mqtt->disconnect();
 
# This is the callback function, when a message arrives for the subscribed topic
sub received 
{
    my ($topic, $message) = @_;
    print STDERR "Incoming message on topic $topic is: $message\n";
}

Get a message from broker only once

If you only want to get a message from a topic once, you have to use a temporarely subscription. Getting a message once isn't implemented in MQTT (in fact MQTT does only know full subscriptions). Note that this only works for topics with the retained flag set!

use Net::MQTT::Simple;
use Time::HiRes qw ( sleep );
 
# Allow unencrypted connection with credentials
$ENV{MQTT_SIMPLE_ALLOW_INSECURE_LOGIN} = 1;
 
# Connect to broker
my $mqtt = Net::MQTT::Simple->new('localhost:1883');
 
# Depending if authentication is required, login to the broker
if($mqtt_username and $mqtt_password) {
    $mqtt->login($mqtt_username, $mqtt_password);
}
 
$mqtt->retain("loxberry/myplugin/temperature", "26.5");
 
my $received = 0;
my $value;
$mqtt->subscribe("loxberry/myplugin/temperature", \&received);
# Wait a maximum of 1 sec.
for (my $i = 0; $i < 10; $i++) {
    last if ($received);
    $mqtt->tick();
    sleep (0.1);
}
$mqtt->unsubscribe("loxberry/myplugin/temperature");
 
print "The message I have received is: $value\n";
 
$mqtt->disconnect();
exit;
 
# This is the callback function, when a message arrives for the subscribed topic
sub received 
{
    $received = 1;
    my ($topic, $message) = @_;
    print STDERR "Incoming message on topic $topic is: $message\n";
    $value = $message if ($message);
}

Last Will and Testament (LWT)

To set LWT, set the LWT message after successfully connecting:

$mqtt->last_will("loxberry/myplugin/status", "Disconnected", 1);

The last will message is automatically sent by the broker, if the connection is lost, or your script dies (or is killed).

If the connection is cleanly closed by the $mqtt→disconnect() call, the LWT is not sent.

Best practices

  • eval { }; all the $mqtt calls for error handling.
  • If you use your own topic path, do not statically use "loxberry" as your base, but use the result of lbhostname() - this is an mqtt recommendation to use unique device names, and your plugin may conflict on multiple LoxBerry installations.
  • On an invalid subscription (e.g. syntax error), the broker immediately will disconnect your connection. 
  • The lib does an automatic reconnect. 
  • For further details on the lib, see Net::MQTT::Simple