Fugu

 view release on metacpan or  search on metacpan

lib/Fugu/MQTT.pm  view on Meta::CPAN

}

sub new ( $class, %args )
{
	my $self = bless {
		host     => $args{host} // '127.0.0.1',
		port     => $args{port} // 1883,
		username => $args{username},
		password => $args{password},

		subscriptions    => {},
		pending_messages => [],
		connected        => 0,
		last_tick        => 0,
	}, $class;

	return $self;
}

sub mqtt_connect ( $self, $timeout = 10 )
{
	Fugu::Log->default->debug(
		'Connecting to MQTT broker at %s:%d (timeout: %ds)',
		$self->{host}, $self->{port}, $timeout );

	# Try to load Net::MQTT::Simple if it is available
	local $@;

	# Capture the warnings from Net::MQTT::Simple
	my @warnings;
	local $SIG{__WARN__} = sub {
		push @warnings, shift;
	};

	# The connect can block in the resolver or the handshake, and a
	# poll loop cannot interrupt either. Thus the guard is an alarm.
	my $success = eval {
		Fugu::Timeout::bounded(
			$timeout,
			sub {

				# On OpenBSD the packages install under
				# site_perl, which a perl started with a
				# pruned @INC does not hold
				unshift @INC,
				    '/usr/local/libdata/perl5/site_perl'
				    unless grep {
					$_ eq
					    '/usr/local/libdata/perl5/site_perl'
				    } @INC;

				require Net::MQTT::Simple;

				my $server = $self->{host};
				if ( $self->{port} != 1883 ) {
					$server .= ':' . $self->{port};
				}

				my $mqtt = Net::MQTT::Simple->new($server);

				# Set the login credentials if the
				# configuration has a username
				if ( defined $self->{username} ) {
					$mqtt->login(
						$self->{username},
						$self->{password} // ''
					);
				}

				$self->{client}    = $mqtt;
				$self->{connected} = 1;
				Fugu::Log->default->debug(
					'Successfully connected to MQTT broker'
				);
				return 1;
			} );
	};

	_log_warnings( 'MQTT connection warning: %s', \@warnings );

	if ( $@ || !$success ) {
		my $err = $@ || "no answer within ${timeout}s";
		Fugu::Log->default->error( 'MQTT connection failed: %s', $err );
		$self->{connected} = 0;
	}

	return $self->{connected};
}

# $self->subscribe($topic, $callback):
#	Subscribe to an MQTT topic with a callback for messages.
#	$callback receives ($topic, $payload).
sub subscribe ( $self, $topic, $callback )
{
	Fugu::Log->default->debug( 'Subscribing to MQTT topic: %s', $topic );
	$self->{subscriptions}{$topic} = $callback;

	return unless $self->{connected} && $self->{client};

	$self->_register($topic);
}

# $self->_register($topic):
#	Register one topic with the client. Net::MQTT::Simple uses a
#	different subscription model: the module registers the topics
#	and polls for messages in tick(). Since 1.33,
#	Net::MQTT::Simple passes a retain flag as a third argument.
#	Accept and ignore all extra arguments.
sub _register ( $self, $topic )
{
	eval {
		$self->{client}->subscribe(
			$topic,
			sub ( $topic_received, $payload, @ ) {
				push @{ $self->{pending_messages} },
				    [ $topic_received, $payload ];
			} );
	};

	if ($@) {
		Fugu::Log->default->error( 'MQTT subscribe error for %s: %s',



( run in 1.556 second using v1.01-cache-2.11-cpan-007c89162af )