NAME

Fugu::MQTT - a subscribing MQTT client for a single-threaded daemon

SYNOPSIS

use Fugu::MQTT;

my $mqtt = Fugu::MQTT->new(
    host => '127.0.0.1',
    port => 1883,
);
$mqtt->mqtt_connect(10) or die "no broker\n";

$mqtt->subscribe('stat/+/RESULT', sub ($topic, $payload) {
    ...
});
$mqtt->publish('cmnd/lamp/POWER', 'ON');

# From the event loop, once each pass
$mqtt->tick;

DESCRIPTION

Fugu::MQTT is a wrapper around Net::MQTT::Simple for a daemon that has one process and one event loop. It never blocks the caller. tick drains what arrived and returns, thus the loop keeps the MQTT connection beside its own descriptors.

Net::MQTT::Simple loads at connect time, not at compile time. Thus the module keeps the core-Perl load contract of Fugu, and a daemon whose broker is optional still starts without the library.

Every message goes through a callback. The module holds the incoming messages in a queue and dispatches them in tick, in the process that called it. A callback thus runs where the caller can reason about it, and never inside a signal handler.

new

new(%args) creates a client. The method opens no socket. Call mqtt_connect.

These are the arguments:

host

The broker. The default is 127.0.0.1.

port

The broker port. The default is 1883.

username

The login name. The client sends no credentials when this argument is absent.

password

The login password.

mqtt_connect

mqtt_connect($timeout) connects to the broker. The default timeout is 10 seconds.

A connect can block in the resolver or in the handshake, and no poll loop can interrupt either. Thus the guard is the alarm of Fugu::Timeout. A broker that does not answer costs the caller the timeout, not the run.

The method returns true when the client is connected.

subscribe

subscribe($topic, $callback) registers a topic and its callback. The callback gets ($topic, $payload), where the topic is the one that arrived, not the pattern.

The pattern accepts the MQTT wildcards: + matches one level and # matches the remaining levels. The module registers the subscription even when the client is not connected, so a caller can subscribe before the broker is up. resubscribe sends the set again after a reconnection.

publish

publish($topic, $payload, $retain) sends one message. A true $retain makes the broker keep the message for the next subscriber. The method does nothing when the client is not connected.

tick

tick($timeout) reads what arrived and runs the callbacks. The default timeout is 0, which does not block. The method returns the number of dispatched messages.

The method reports a lost connection: it clears the connected state and returns 0. The caller then calls reconnect on a schedule of its own.

reconnect

reconnect disconnects, connects again, and subscribes again. The method returns 1 on success and 0 on failure.

resubscribe

resubscribe sends every registered subscription to the broker again. reconnect calls it. A caller needs it only when it connects by itself.

disconnect

disconnect closes the connection and discards the queued messages. The registered subscriptions stay, thus a later reconnect restores them.

is_connected

is_connected reports if the client holds a connection.

subscriptions

subscriptions returns the registered topic patterns.

RETURN VALUES

mqtt_connect and is_connected return true when the client is connected. reconnect returns 1 or 0. tick returns a count. subscriptions returns a list.

No method dies. A broker error, a bad callback, and a lost connection all go to the log of Fugu::Log. A daemon must not exit because a broker went away.

EXAMPLES

This example reconnects when the broker goes away:

$loop->every(1, sub {
    $mqtt->tick;
    $mqtt->reconnect unless $mqtt->is_connected;
});

SEE ALSO

Fugu::Log, Fugu::Timeout, Net::MQTT::Simple

AUTHORS

Dick Olsson <hi@senzilla.io>

CAVEATS

A callback runs inside tick. A callback that blocks blocks the loop. Keep the work in a callback short, or queue it.

The module holds no quality of service beyond what Net::MQTT::Simple gives, which is QoS 0. A message can be lost. A caller that must know a device answered reads the state topic of that device.