Community discussions

MikroTik App
 
User avatar
luqasz
Member Candidate
Member Candidate
Topic Author
Posts: 101
Joined: Thu Aug 16, 2007 9:53 pm
Location: Poland

api queries. complex queries. please explain

Wed May 01, 2013 4:14 am

hi

i would like to use queries more frequently. problem is that i do not understand all that is written on wiki.
considder following examples:

i have a routerboard with 5 ethernet interfaces, 1 wlan, 1 bridge

print all interfaces that are not type=wlan and type=bridge
/interface/print
=.proplist=type,.id
?type=wlan
?#!
?type=bridge
?#|
above works well

but this one:
/interface/print
=.proplist=type,.id
?type=wlan
?#!
?type=bridge
?#!
?#|
should return all interfaces that are not in type= wlan,bridge. i should get all ethernet interfaces only. in return i get all interfaces. it doesn't make sense to me.
/interface/print
=.proplist=type,.id
?type=wlan
?type=bridge
?#|!
this one returns all ethernet interfaces only.
/interface/print
=.proplist=type,.id
?type=wlan
?type=bridge
?#&!
this returns all interfaces.
how does it correspond to De Morgan's law ?
! character replaces top value with the opposite.
from what is written you can understand that ! character always corresponds to the item at index = 0. if it does how to negate items at other indexes ?
what is a "top value" ?

on wiki in table where operations are described word 'character' is frequently used. what kind of character ? what characters are allowed ?
/interface/print
=.proplist=type,.id
?type=wlan
?#!
?type=bridge
?#!
?#|
in above example indexes in stack are:
?type=wlan has stack index = 0
?type=bridge has stack index = 1
am i correct ?
index that is followed by a character pushes copy of value at that index.
again the question. witch character ?
index that is followed by the end of word replaces all values with the value at that index.
if i write:
/interface/print
?type=wlan
?name=bridge
?#0
it will be transformed into:
/interface/print
?type=wlan
?name=wlan
am i right ?
sequence of decimal digits followed by any other character or end of word is interpreted as a stack index. top value has index 0.
what does it mean ?
000101023123!

"000101023123" is a sequence of decimal digits
what index is it ?
. after another character pushes copy of top value.
so it means that a "." will always point in value at stack index = 0 ?
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: api queries. complex queries. please explain

Wed May 01, 2013 4:24 pm

As the spec says, all items are placed on a "stack". So, "top value" refers to the top of said stack at that point in time.

So... let's look at this line by line:
?type=wlan
?#!
?type=bridge
?#!
?#|
1.
?type=wlan
The scripting equivalent of
where type=wlan
2.
?#!
pops a value, and pushes back the opposite, i.e. the scripting equivalent of
where !(type=wlan)
3.
?type=bridge
Unless otherwise told later on, this ends up acting as an "or", i.e. the scripting equivalent of
where !(type=wlan) || type=bridge
(keep in mind that now, "type=bridge" is at the top of the stack, while "!(type=wlan)" is after it)
4.
?#!
Pops the last value, negates it, and pushes the result back on the stack, i.e. the scripting equivalent of
where !(type=wlan) || !(type=bridge)
5.
?#|
Pops two values, "or"s them, and pushes the result back on the stack. In this case, the query would match the same stuff with or without that line, i.e. we have
where (!(type=wlan) || !(type=bridge))
I don't think this is what you're after, since even in scripting, this would output all interfaces. That's because "or" short circuits - if the left part is true, the right is never checked. So, when RouterOS is evaluating an interface of type "bridge" - that's not "wlan", so it goes in the result set. And when an interface of type "wlan" comes in - it's first false, but then the "or" becomes true since "wlan" is not "bridge".

You want to "and" those instead, i.e.
?type=wlan
?#!
?type=bridge
?#!
?#&
which is a scripting equivalent of
where (!(type=wlan) && !(type=bridge))
or, as you've already discovered yourself, you can compact that into
?type=wlan
?type=bridge
?#|!
which would be the scripting equivalent of
where !(type=wlan || type=bridge)
because in that case, the stack is initially made of "type=wlan" at the bottom, and "type=bridge" at the top - you take those two, or them, and push the result back on the stack. You have exactly one value in the stack now, which is then negated.



P.S. If you're using PHP, with my client, it's slightly easier, in that you can simply think of every next step as adding the operation and placing "()" around everything, e.g.
RouterOS\Query::where('type', 'wlan') // (type=wlan)
->orWhere('type', 'bridge') // ((type=wlan) || (type=bridge))
->not() // (!((type=wlan) || (type=bridge)))
->andWhere('mtu', 1500);// ((!((type=wlan) || (type=bridge))) && mtu=1500)   
I'm planning on eventually making a string parser so that people can write the scripting equivalents, but I haven't made one yet.
 
User avatar
luqasz
Member Candidate
Member Candidate
Topic Author
Posts: 101
Joined: Thu Aug 16, 2007 9:53 pm
Location: Poland

Re: api queries. complex queries. please explain

Wed May 01, 2013 7:07 pm

thx for your reply. it did answer some questions.

/interface/print
?type=wlan
?#!
?type=bridge
?#!
?#&
is equivalent to
/interface/print
?type=wlan
?type=bridge
?#|!
ok got that.

above is the same as:
(!a && !b) == !(a || b)
but how to write this:
!(a && b) == (!a || !b)
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: api queries. complex queries. please explain

Wed May 01, 2013 7:28 pm

!(a && b)
would be
?a
?b
?#&!
and
(!a || !b)
would be
?a
?#!
?b
?#!|
In their shortest (yet understandable...) form that is.



As a general rule... convert the expression to Reverse Polish Notation.
 
User avatar
luqasz
Member Candidate
Member Candidate
Topic Author
Posts: 101
Joined: Thu Aug 16, 2007 9:53 pm
Location: Poland

Re: api queries. complex queries. please explain

Thu May 02, 2013 11:38 am

thx for reply

my goal is to write some wrapper for queries so when someone will use my api implementation (in python3) he/she will not have to learn query syntax.

for example:
query('/interface').where(query.type == 'ethernet').returning(query.id)
this will show all ethernet interfaces with =.proplist=.id

it is just an begining so above may change.
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: api queries. complex queries. please explain

Thu May 02, 2013 3:39 pm

The functions that I use can be found at SQL abstraction APIs ("Zend Framework 1"'s Zend_Db_Select in particular), which is why I settled for them, and would recommend in case you don't have anything better.

I don't know Python enough to know about any SQL abstraction APIs, but if you know some, I'd highly recommend you make your API close to that, as this is what Python programmers are likely to already know.

Alternatively, you could try doing the very thing I haven't yet done - an expression parser, so that the scripting equivalents can be written directly as strings, as opposed to indirectly with methods, which is what any abstraction API does by definition.

Also, side note: ".proplist" is an attribute word, not a query word. It could (if you let it...) go into the same place(s) where users would normally specify arguments (e.g. "detail", "stats", etc.).
 
User avatar
luqasz
Member Candidate
Member Candidate
Topic Author
Posts: 101
Joined: Thu Aug 16, 2007 9:53 pm
Location: Poland

Re: api queries. complex queries. please explain

Thu May 02, 2013 3:53 pm

Also, side note: ".proplist" is an attribute word, not a query word. It could (if you let it...) go into the same place where users would normally specify arguments (e.g. "detail", "stats", etc.).
i don't want to distinguish normal print and print with querry. in a sense of different methods.
query('/interface').where(query.type == 'ethernet').returning(query.id)
you could also use
query('/interface').returning(query.id)
thus for second command
/interface/print
=.proplist=.id
will be executed
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: api queries. complex queries. please explain

Thu May 02, 2013 4:27 pm

OK, but what if I want to specify additional arguments to the print (e.g. detail)?

An additional "fixed" method? e.g.
query('/interface').detail().returning()
This means you'll need to release a new version of your client with new methods every time MikroTik adds a new argument to print (which, in fairness, is rarely, but still...).

An additional method accepting such arguments or an additional argument? e.g.
query('/interface', {'detail': '', 'stats': ''}).returning()
This means returning()'s argument becomes kind'a pointless, since one may as well do
query('/interface', {'detail': '', 'stats': '', '.proplist': '.id,tx-byte,rx-byte'}).returning()
It's your decision in the end of course... just be aware of both choice's consequences.
 
maxfava
Member Candidate
Member Candidate
Posts: 224
Joined: Mon Oct 17, 2005 12:30 am

Re: api queries. complex queries. please explain

Thu Jan 16, 2014 12:40 am

Very simple question

I want to disconnect a user from ppp active
so I send
/ppp/active/remove
?name=value

it returns done
but that user specified in the value is not disconnected.
any input?
 
User avatar
luqasz
Member Candidate
Member Candidate
Topic Author
Posts: 101
Joined: Thu Aug 16, 2007 9:53 pm
Location: Poland

Re: api queries. complex queries. please explain

Thu Jan 16, 2014 11:49 am

Very simple question

I want to disconnect a user from ppp active
so I send
/ppp/active/remove
?name=value

it returns done
but that user specified in the value is not disconnected.
any input?
http://wiki.mikrotik.com/wiki/API#Queries
Api queries are not supported in commands other than print/getall. What you have posted is clearly a bug/confusing behavior of api. if queries are not supported in commands other than print/getall this should fail with approprieate error. i have tried with =name and with =.id. effect is still the same.

i suggest posting this issue to mikrotik support.
 
maxfava
Member Candidate
Member Candidate
Posts: 224
Joined: Mon Oct 17, 2005 12:30 am

Re: api queries. complex queries. please explain

Fri Jan 17, 2014 2:10 pm

Thansk
at the end I found the solution, print with appropriate query and get the .id and then execute the remove command to specific .id and it works

I agree that if I send remove with filter ?name=xx and it is not supported instead to return !done shoudl return something like ?name not supported in remove command.

Massimo
 
User avatar
Deantwo
Member
Member
Posts: 331
Joined: Tue Sep 30, 2014 4:07 pm

Re: api queries. complex queries. please explain

Mon Jan 18, 2016 4:49 pm

I see no mention of querying for "begins with x", "ends with x", or "contains x". Is this simply not possibly?

CLI examples:
/interface print where name~"^ether"
/interface print where name~"gateway$"
/interface print where name~"master"
Last edited by Deantwo on Fri Aug 10, 2018 3:18 pm, edited 2 times in total.
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: api queries. complex queries. please explain

Mon Jan 18, 2016 5:33 pm

I see no mention of querying for "begins with x", "ends with x", or "contains x". Is this simply not possibly?

CLI examples:
/interface print where name~"^ether"
/interface print where name~"gateway$"
/interface print where name~"master"
It's not possible... yet (hopefully).

See this topic.
 
Abdulrahman
just joined
Posts: 4
Joined: Mon Mar 26, 2018 8:29 pm

Thanks a lot , it works using the .id

Mon Apr 09, 2018 5:34 pm

Thanks a lot , it works using the .id
Thansk
at the end I found the solution, print with appropriate query and get the .id and then execute the remove command to specific .id and it works

I agree that if I send remove with filter ?name=xx and it is not supported instead to return !done shoudl return something like ?name not supported in remove command.

Massimo
 
phamthinh2707
just joined
Posts: 5
Joined: Thu Sep 27, 2018 6:04 am

Re: api queries. complex queries. please explain

Thu Sep 27, 2018 6:11 am

I'm doing my winforms app to connect to Mikrotik router using tik4net right now. I'm setting up Wifi Marketing and have some trouble with convert to API command:
Example:
/interface wireless set [ find default-name=wlan1 ] disabled=no mode=ap-bridge ssid="Testing Wifi Marketing"
My Convert:
/interface/wireless/set
?default-name=wlan1
=disabled=no
=mode=ap-bridge
=ssid=Testing Wifi Marketing
 
nescafe2002
Forum Veteran
Forum Veteran
Posts: 897
Joined: Tue Aug 11, 2015 12:46 pm
Location: Netherlands

Re: api queries. complex queries. please explain

Thu Sep 27, 2018 10:50 am

API does not support query in set operations. Split your action into two commands:

- Print
- Set

Print:
/interface/wireless/print
?default-name=wlan1
=.proplist=.id

Result:

!re
=.id=*C
!done

Set with id = *C (in this example):

/interface/wireless/set
=disabled=no
=mode=ap-bridge
=ssid=Testing Wifi Marketing
=.id=*C

Result:

!done



Now you've mentioned tik4net, this is much easier:

  using (var conn = tik4net.ConnectionFactory.OpenConnection(TikConnectionType.Api, "192.168.88.1", 8728, "admin", "password"))
  {
    var obj = conn.LoadList<InterfaceWireless>(conn.CreateParameter("default-name", "wlan1")).First();
    obj.Disabled = false;
    obj.Mode = tik4net.Objects.Interface.InterfaceWireless.WirelessMode.ApBridge;
    obj.Ssid = "Testing Wifi Marketing";
    conn.Save(obj);
  }
 
rJIaB6yX
just joined
Posts: 1
Joined: Thu Jul 21, 2022 2:32 pm

Re: api queries. complex queries. please explain

Thu Jul 21, 2022 2:39 pm

Hi
Help with compiling a Linux command for api mikrotik, displaying the MAC address of the pppoe interface with the specified "remote-address".
Waiting for something similar to:
read ip int mac t <<< "$(send_mikrotik_cmd "$ip" "${telnet_login}" "${telnet_password}" /ip arp print .proplist=address,mac-address,interface ?address=${remote-address})"
That's for IP interfaces, but i need pppoe, and "/ip arp" is not suitable.
Thanks in advance
Last edited by rJIaB6yX on Thu Jul 21, 2022 2:42 pm, edited 1 time in total.

Who is online

Users browsing this forum: Bing [Bot], itamx and 79 guests