NAME

MikroTik::Client - Non-blocking interface to MikroTik API

SYNOPSIS

my $api = MikroTik::Client->new();

# Blocking
my $list = $api->command(
    '/interface/print',
    {'.proplist' => '.id,name,type'},
    {type        => ['ipip-tunnel', 'gre-tunnel'], running => 'true'}
);
if (my $err = $api->error) { die "$err\n" }
printf "%s: %s\n", $_->{name}, $_->{type} for @$list;


# Non-blocking
my $tag = $api->command(
    '/system/resource/print',
    {'.proplist' => 'board-name,version,uptime'} => sub {
        my ($api, $err, $list) = @_;
        ...;
        Mojo::IOLoop->stop;
    }
);
Mojo::IOLoop->start;

# Subscribe
$tag = $api->subscribe(
    '/interface/listen' => sub {
        my ($api, $err, $el) = @_;
        ...;
    }
);
Mojo::IOLoop->timer(3 => sub { $api->cancel($tag) });
Mojo::IOLoop->start;

# Errors handling
$api->command(
    '/random/command' => sub {
        my ($api, $err, $list) = @_;

        if ($err) {
            warn "Error: $err, category: " . $list->[0]{category};
            return;
        }

        ...;
    }
);
Mojo::IOLoop->start;

# Promises
$api->cmd_p('/interface/print')
    ->then(sub { my $res = shift }, sub { my ($err, $attr) = @_ })
    ->finally(sub { Mojo::IOLoop->stop });
Mojo::IOLoop->start;

DESCRIPTION

Both blocking and non-blocking interface to a MikroTik API service. With queries, command subscriptions and Promises/A+.

CHANGES

Starting from v0.600 this module switched back to using Mojo::IOLoop as event loop backend. This should not affect blocking calls, but it might break non-blocking ones. Since both Mojo::IOLoop and AnyEvent prefer using EV, when it's available, it should not really matter which one starts an event loop.

For other event systems you can set MOJO_REACTOR environment variable to MikroTik::Client::Reactor::AE. It would force Mojo::IOLoop to play a bit more nicely with AnyEvent.

BEGIN {
    $ENV{MOJO_REACTOR} = "MikroTik::Client::Reactor::AE";
}

use AnyEvent;
use AnyEvent::Loop;

my $done = AE::cv;
$api->command('/some/command' => $done);
$done->recv;

ATTRIBUTES

MikroTik::Client implements the following attributes.

ca

my $ca = $api->ca;
$api->ca("/etc/ssl/certs/ca-bundle.crt")

Path to TLS authority file.

Can be changed with MIKROTIK_CLIENT_CA environment variable.

cert

my $cert = $api->cert;
$api->cert("./client.crt")

Path to the TLS cert file.

Can be bundled with a private key and intermediate public certificates. If it's contains a private key, key attribute is optional.

Can be changed with MIKROTIK_CLIENT_CERT environment variable.

error

my $last_error = $api->error;

Keeps an error from last "command" call. Empty string on successful commands.

host

my $host = $api->host;
$api     = $api->host('border-gw.local');

Host name or IP address to connect to. Defaults to 192.168.88.1.

insecure

my $insecure = $api->insecure;
$api->insecure(0);

Do not verify TLS certificates. Connection will be encrypted, but peer certificate won't be validated. Enabled by default.

Can be changed with MIKROTIK_CLIENT_INSECURE environment variable.

ioloop

my $loop = $api->ioloop;
$api     = $api->loop(Mojo::IOLoop->new());

Event loop instance to use for blocking calls. Defaults to Mojo::IOLoop object.

key

my $key = $api->key;
$api->key("./client.crt")

Path to TLS key file. Optional if a private key is bundled with cert file.

Can be changed with MIKROTIK_CLIENT_KEY environment variable.

new_login

my $new_login = $api->new_login;
$api          = $api->new_login(0);

Used to enable new login scheme introduced in RouterOS v6.43. Now it's a way to disable it, if required for some reason. Enabled by default.

password

my $pass = $api->password;
$api     = $api->password('secret');

Password for authentication. Empty string by default.

port

my $port = $api->port;
$api     = $api->port(8000);

API service port for connection. Defaults to 8729 and 8728 for TLS and clear text connections respectively.

timeout

my $timeout = $api->timeout;
$api        = $api->timeout(15);

Timeout in seconds for sending request and receiving response before command will be canceled. Default is 10 seconds.

tls

my $tls = $api->tls;
$api    = $api->tls(1);

Use TLS for connection. Enabled by default.

CAVEAT: It's enabled by default, but it requires TLS support from "connect1" in Mojo::IOLoop::Client

user

my $user = $api->user;
$api     = $api->user('admin');

User name for authentication. Defaults to admin.

METHODS

cancel

# subscribe to a command output
my $tag = $api->subscribe('/ping', {address => '127.0.0.1'} => sub {...});

# cancel command after 10 seconds
Mojo::IOLoop->timer(10 => sub { $api->cancel($tag) });

# or with callback
$api->cancel($tag => sub {...});

Cancels background commands. Can accept a callback as last argument.

cmd

my $list = $api->cmd('/interface/print');

An alias for "command".

cmd_p

my $p = $api->cmd_p('/interface/print');

An alias for "command_p".

command

my $command = '/interface/print';
my $attr    = {'.proplist' => '.id,name,type'};
my $query   = {type => ['ipip-tunnel', 'gre-tunnel'], running => 'true'};

my $list = $api->command($command, $attr, $query);
die $api->error if $api->error;
for (@$list) {...}

$api->command('/user/set', {'.id' => 'admin', comment => 'System admin'});

# Non-blocking
$api->command('/ip/address/print' => sub {
    my ($api, $err, $list) = @_;

    return if $err;

    for (@$list) {...}
});

# Omit attributes
$api->command('/user/print', undef, {name => 'admin'} => sub {...});

# Errors handling
$list = $api->command('/random/command');
if (my $err = $api->error) {
    die "Error: $err, category: " . $list->[0]{category};
}

Executes commands on a device. Returns Mojo::Collection of hashrefs with results. Can accept a callback for non-blocking calls.

On errors it may pass extra info in return argument in addition to an error value.

For a query syntax refer to MikroTik::Client::Query.

command_p

my $promise = $api->command_p('/interface/print');

$promise->then(
sub {
    my $res = shift;
    ...
})->catch(sub {
    my ($err, $attr) = @_;
});

Same as "command", but always performs requests non-blocking and returns a Mojo::Promise object instead of accepting a callback.

subscribe

my $tag = $api->subscribe('/ping',
    {address => '127.0.0.1'} => sub {
      my ($api, $err, $res) = @_;
    });

Mojo::IOLoop->timer(
    3 => sub { $api->cancel($tag) }
);

Subscribe to a command with continuous responses such as listen or ping. Should be terminated with "cancel".

DEBUGGING

You can set the MIKROTIK_CLIENT_DEBUG environment variable to get some debug output printed to stderr.

Also, you can change connection timeout with the MIKROTIK_CLIENT_CONNTIMEOUT variable.

COPYRIGHT AND LICENSE

Andre Parker, 2017-2025.

This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.

SEE ALSO

https://help.mikrotik.com/docs/spaces/ROS/pages/47579160/API, https://codeberg.org/anparker/mikrotik-client