Print ppps from 2 Router Mikrotik in same code PEAR2 PHP

Hi, im here again, and now im trying print again the active connections and ppp’s, but now, from 2 routers..

Here is the code:

<?php use PEAR2\Net\RouterOS; // require_once 'pear2\src\PEAR2\Autoload.php'; require_once 'PEAR2_Net_RouterOS-1.0.0b4.phar'; //Conexion a Mikrotik //IP MIKROTIK //Usuario //Password $client = new RouterOS\Client('xxx.xxx.xxx.xxx', 'victor', 'victor'); $client2 = new RouterOS\Client('xxx.xxx.xxx.xxx','victor','victor'); //$client3 = new RouterOS\Client('','',''); //$client4 = new RouterOS\Client('','',''); //$client5 = new RouterOS\Client('','',''); //Reiniciar PPP $remove=new RouterOs\Request("/ppp/active/remove"); $remove->setArgument('numbers', $itemID); // Tabla echo ""; echo ""; //Actualizar pagina //echo ""; $ppp1= $client->sendSync(new RouterOS\Request('/ppp/active/print'))->getAllOfType(RouterOS\Response::TYPE_DATA); $ppp2= $client2->sendSync(new RouterOS\Request('/ppp/active/print'))->getAllOfType(RouterOS\Response::TYPE_DATA); $ppps = array_merge_recursive ($ppp1, $ppp2); $interfaceQuery = RouterOS\Query::where('name', $ppps->getArgument('name')); while ($ppp = $ppps->next()) { $interfaceQuery->orWhere('name', $ppp('name')); } $ac1= $client->sendSync(new RouterOS\Request('/interface/pppoe-server/print', $interfaceQuery))->getAllOfType(RouterOS\Response::TYPE_DATA)->toArray(); $ac2= $client2->sendSync(new RouterOS\Request('/interface/pppoe-server/print', $interfaceQuery))->getAllOfType(RouterOS\Response::TYPE_DATA)->toArray(); $activeInterfaces = array_merge_recursive($ac1, $ac2); foreach ($ppps as $ppp) { $id = $ppp('.id'); $service = ''; foreach ($activeInterfaces as $index => $pppInterface) { if ($pppInterface('name') === $ppp('name')) { $service = $pppInterface('service'); break; } } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo "
NombreServicioTiempo ActivoDireccionReiniciar
". $ppp('name') ."" . $service . "" . $ppp('uptime'). "". $ppp('address') ."Reiniciar
"; ?>

You have forgotten the toArray() call at $ppp1 and $ppp2.

For the sake of performance, you might want to move away your requests into a variable that you then pass to all clients. Also, if there’s a potentially growing list of routers (i.e. Client objects), consider placing them in an array instead, as this will let you more elegantly call the request on all of them - by just looping over the array with a foreach, and calling sendSync() on each.

Pff…I don’t know how to do that.. :S

Which part?

The toArray() call? You already did it here:

$ac1= $client->sendSync(new RouterOS\Request('/interface/pppoe-server/print', $interfaceQuery))->getAllOfType(RouterOS\Response::TYPE_DATA)->toArray(); 

it’s the same deal. To make a call to a method simply means adding “->” and the method name to the end of an object (be it from a variable, or as above, from what another method call has returned an object).

The putting a request to a variable part? You have done this here:

$remove=new RouterOs\Request("/ppp/active/remove");
$remove->setArgument('numbers', $itemID); 

The variable $remove contains a Request object. The part

new RouterOS\Request

is what creates an object, in this case a “RouterOS\Request” object. You may store it into a variable, or directly give it to the sendSync() method, as you have done here:

sendSync(new RouterOS\Request('/ppp/active/print')) 

Doing

sendSync($remove) 

would pass the object inside the variable $remove to be sent using sendSync().

So… same deal for any other request.


The Client objects into an array? Really now? Here’s a tutorial for syntax for arrays. As just mentioned, the part

new ...() 

is how you create an object (replacing “…” with the type of object, of course). The whole thing works in the same fashion as how quotes delimit a string. The only difference is that instead of then having a string into the array, you’re having an object at that same point. How you do an array of strings, you can see in the tutorial above.

Hi again, i can connect 6 different routers mikrotik now..But i have a little problem. If i have 1 router turn off, the script doesnt work :S

For each router i copy and paste this:

<?php flush(); //Consulta al Primer cliente Mikrotik para sacar el listado ($client) //Imprime la informacion de Active connections de Mikrotik y lo almacena en el Array $ppps = $client->sendSync(new RouterOS\Request('/ppp/active/print'))->getAllOfType(RouterOS\Response::TYPE_DATA); $interfaceQuery = RouterOS\Query::where('name', $ppps->getArgument('name')); while ($ppp = $ppps->next()) { $interfaceQuery->orWhere('name', $ppp('name')); } //Imprime la informacion de Interfaces/PPPoe Servers de Mikrotik y lo almacena en el Array $activeInterfaces = $client->sendSync(new RouterOS\Request('/interface pppoe-server print', $interfaceQuery))->getAllOfType(RouterOS\Response::TYPE_DATA)->toArray(); //Para cada pppoe, imprimira una fila con los valores que se necesitan foreach ($ppps as $ppp) { $id = $ppp('.id'); //Agrega el id a cada fila, para que tenga un valor unico cada una $service = ''; //Compara el nombre de PPPoe-server de Interfaces con el de Active Connections, y asi relacionar el Service foreach ($activeInterfaces as $index => $pppInterface) { if ($pppInterface('name') === $ppp('name')) { $service = $pppInterface('service'); break; } } //Imprime una fila en la tabla por cada registro echo ""; echo "" . src ($ip1) . ""; //Cabecera echo "" . $ppp('name') . ""; //Nombre echo "" . $service . ""; //Servicio echo "" . router($ppp ('caller-id')) . ""; //MAC echo "" . $ppp('uptime') . ""; //Tiempo activo echo "" . $ppp('address') . ""; //Direccion //Boton para Reiniciar la conexion activa echo " Reiniciar "; } ?>

I only change the $client (client2, client3…)

Now, i need print all active routers, and ignore the disable routers :S

Maybe with a ping before the request, and if it works, print the request, if not, it alerts me..
The problem is, how i can ping the router before the request?

pd: Can I ignore the router with otherwise more simple?

pd2: I have this now:

<?php try { $client = new RouterOS\Client($ip, 'vito', 'vito'); } catch (Exception $e) { ?>
Imposible Conectarse a <?php echo $ip?>
<?php
		}But i dont know if its work perfectly, because the router is now online, and i cant turn off it..

Anyways i test it in other script, and i have 2 alerts:
Notice: Undefined variable: client in C:\wamp\www\addresses.php on line 46
Fatal error: Call to a member function sendSync() on a non-object in C:\wamp\www\addresses.php on line 46

Can i ignore them in PHP.ini? Are they important alerts?

The errors are due to your script trying to connect to the router despite the failed connection.

The best way to deal with this is to encapsulate your whole per-router script into a “try…catch” section, not just the “new RouterOS\Client” part.

For each router i copy and paste

Eww… Seriously dude! Arrays!!! They’re your friends. Get to know them!

Add the details for each router into an array, and loop over it for each router. e.g.

<?php



$routers = array(
    array('192.168.0.1', 'vito', 'vito'),
    array('xxx.xxx.xxx.xxx', 'victor', 'victor'),
);

foreach ($routers as $router) {
        try {
            $client = new RouterOS\Client($router[0], $router[1], $router[2]);

            //Rest of the per-router script

        } catch (Exception $e)
          {
        ?><div>Imposible Conectarse a <?php echo $router[0];?></div>
    <?php
          }
}

It looks nice! Thanks again :slight_smile:

But i have a little problem again..
I have this now:

Listado ByWifi @import "tabs/css/demo_page.css"; @import "tabs/css/demo_table_jui.css"; @import "tabs/css/jquery-ui-1.8.4.custom.css"; @import "tabs/css/TableTools_JUI.css"; @import "tabs/css/selector.css"; .ui-tabs .ui-tabs-panel { padding: 10px } <?php //Conexion a la API de MIKROTIK use PEAR2\Net\RouterOS; // require_once 'pear2\src\PEAR2\Autoload.php'; require_once 'PEAR2_Net_RouterOS-1.0.0b4.phar'; //API Mikrotik PEAR2 mas info en : https://github.com/pear2/Net_RouterOS/wiki//Botones de Modificar, Borrar y Añadir reglas de NAT if (isset($_POST['act'])) { foreach ($_POST['act'] as $act => $itemID) { if (in_array($act, array('set', 'remove', 'add'))) { $actionRequest = new RouterOS\Request("/ppp/active/{$act}"); if ('add' !== $act) //Si es set o remove (distinto de add) { $actionRequest->setArgument('numbers', $itemID); } if ('set' === $act || 'add' === $act) { if (isset($_POST[$itemID]['chain'])) { if ('srcnat' === $_POST[$itemID]['chain']) { $_POST[$itemID]['action'] = 'src-nat'; } elseif ('dstnat' === $_POST[$itemID]['chain']) { $_POST[$itemID]['action'] = 'dst-nat'; } } foreach ($_POST[$itemID] as $name => $value) { if ('' != $value) { $actionRequest->setArgument($name, $value); } } } $responses = $client->sendSync($actionRequest); //Alertas de error $errors = $responses->getAllOfType(RouterOS\Response::TYPE_ERROR); if (0 === count($errors)) { header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); return; } else { echo '
    '; foreach ($errors as $error) { echo '
  • ' . $error('message') . '
  • '; } echo '
'; } } } } //FUNCION CABECERA //Le da nombre a la cabecera que nos conectamos (Columna cabecera de la tabla) function src($ip) { switch ($ip) { case 'x.x.x.x': //Primer Cliente return "Cabarga"; break; case 'x.x.x.x': //Segundo Cliente return "Ibio"; break; case 'x.x.x.x': //Tercer Cliente return "Santillana"; break; case 'x.x.x.x': //Cuarto Cliente return "Gornazo"; break; case 'x.x.x.x': //Quinto Cliente return "CRA"; break; case 'x.x.x.x': //Sexto Cliente return "Liebana"; break; } } //Funcion Router function router($mac){ $x = substr($mac, 0, 5); if ($x=='00:27' || $x=='DC:9F' || $x=='24:A4' ) { return 'Ubiquiti'; }elseif ($x=='00:13'){ return 'Eminent'; }elseif ($x=='00:1D' || $x=='00:50'){ return 'DrayTek'; }elseif ($x=='00:0C' || $x=='00:21' || $x=='D4:CA' ){ return 'Mikrotik'; }elseif ($x=='B0:48' || $x=='54:E6' ){ return 'TPLink'; }elseif ($x=='C8:3A'){ return 'Tenda'; }elseif ($x=='00:15'){ //La mayoria son Ubiquity return 'Ubiquiti'; }else{ return 'Desconocido'; } } ?>
<body id="dt_example">
	<div id="container">
		<div id="demo">
			<div id="tabs">			
				<div id="tabs-1">
<?php //IP del Mikrotik al que queremos conectarnos $ip1='xxx.xxx.xxx.xxx'; //Cabarga $ip2='xxx.xxx.xxx.xxx'; //Ibio $ip3='xxx.xxx.xxx.xxx'; //Santillana $ip4='xxx.xxx.xxx.xxx'; //Gornazo $ip5='xxx.xxx.xxx.xxx'; //CRA $ip6='xxx.xxx.xxx.xxx'; //Liebana //conexion al cliente Mikrotik $routers = array( array($ip1, 'vito', 'vito'), array($ip2, 'vito', 'vito'), array($ip3, 'vito', 'vito'), array($ip4, 'vito', 'vito'), array($ip5, 'vito', 'vito'), array($ip6, 'vito', 'vito'), ); foreach ($routers as $router) { try { $client = new RouterOS\Client($router[0], $router[1], $router[2]); //Imprime la informacion de Active connections de Mikrotik y lo almacena en el Array $ppps = $client->sendSync(new RouterOS\Request('/ppp/active/print'))->getAllOfType(RouterOS\Response::TYPE_DATA); $interfaceQuery = RouterOS\Query::where('name', $ppps->getArgument('name')); while ($ppp = $ppps->next()) { $interfaceQuery->orWhere('name', $ppp('name')); } //Imprime la informacion de Interfaces/PPPoe Servers de Mikrotik y lo almacena en el Array $activeInterfaces = $client->sendSync(new RouterOS\Request('/interface pppoe-server print', $interfaceQuery))->getAllOfType(RouterOS\Response::TYPE_DATA)->toArray(); //Para cada pppoe, imprimira una fila con los valores que se necesitan foreach ($ppps as $ppp) { $id = $ppp('.id'); //Agrega el id a cada fila, para que tenga un valor unico cada una $service = ''; //Compara el nombre de PPPoe-server de Interfaces con el de Active Connections, y asi relacionar el Service foreach ($activeInterfaces as $index => $pppInterface) { if ($pppInterface('name') === $ppp('name')) { $service = $pppInterface('service'); break; } } //Imprime una fila en la tabla por cada registro echo ""; echo ""; //Cabecera echo ""; //Nombre echo ""; //Servicio echo ""; //MAC echo ""; //Tiempo activo echo ""; //Direccion //Boton para Reiniciar la conexion activa echo ""; } } catch (Exception $e) { ?>
Imposible Conectarse a <?php echo $router[0];?>
<?php
      }

}
?>

Cabecera Nombre Servicio Modelo Tiempo Activo Direccion Reiniciar
" . src ($router[0]) . "" . $ppp('name') . "" . $service . "" . router($ppp ('caller-id')) . "" . $ppp('uptime') . "" . $ppp('address') . " Reiniciar
				</div>
			</div>
		</div>
	</div>		
    <script type="text/javascript" charset="utf-8" src="tabs/js/jquery.js"></script>
	<script type="text/javascript" charset="utf-8" src="tabs/js/jquery.dataTables.js"></script>
	<script type="text/javascript" charset="utf-8" src="tabs/js/jquery-ui-tabs.js"></script>
	<script type="text/javascript" charset="utf-8" src="tabs/js/ZeroClipboard.js"></script>
	<script type="text/javascript" charset="utf-8" src="tabs/js/TableTools.js"></script>
	<script type="text/javascript" charset="utf-8">
             ...
	</script>
</body>
3 alerts: Notice: Undefined offset: 3 in C:\wamp\www\tabla\tabspruebas2.php on line 206 (line 206 is " $client = new RouterOS\Client($router[0], $router[1], $router[2], $router[3], $router[4], $router[5]);") Undefined offset: 4 in C:\wamp\www\tabla\tabspruebas2.php on line 206 Undefined offset: 4 in C:\wamp\www\tabla\tabspruebas2.php on line 206 \ \ UPDATE: Nevermind, my bad, i thought that each router in routers was an array, but not. I only need router(0), (1), (2). I update the code.

But now, we have problem with API : Maximum execution time of 30 seconds exceeded in phar://C:/wamp/www/tabla/PEAR2_Net_RouterOS-1.0.0b4.phar/PEAR2_Net_RouterOS-1.0.0b4/src/PEAR2/Net/RouterOS/Message.php on line 142

UPDATE2: That problem is when an router is power off or i can’t connect with it, because i changed an IP to test it.
Now, i have all ip’s fine.. But it still not working perfectly :S
The script doesnt print all routers..

If a router is turned off, there’s nothing you can really do about it.

You can specify a maximum number of seconds to wait for the connection to be established, but if you have too many routers, you can still exhaust PHP’s 30 seconds timeout. You can do that at the 6th argument at “new RouterOS\Client”. Leave the 4th and 5th to “null”.

But IMHO, the best way - one I’d recommend - is that you simply don’t connect over ALL routers at once, but one at a time, perhaps from dropdown menu or whatever.

I know, but this script isn’t for me :S I need print all routers in the same table, and then i have a Jquery(Datatables) to sort and filter the info..


P.d: The problem is that im networked computer systems administrator, not a programmer, therefore im a bit bad with PHP :S I only know the basic of programming..

UPDATE: The script with arrays works fine now..But when a put a wrong IP, to fail the connection, the try-catch doesnt work.
It should show me "

?><div>Imposible Conectarse a <?php echo $router[0];?></div>

" Right?

UPDATE2: SOLVED! I have to change some }
} catch (Exception $e)
{
?>

<div>Imposible Conectarse a <?php echo src($router[0]);?></div>

<?php
      }

}
?>