Community discussions

MikroTik App
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Print ppps from 2 Router Mikrotik in same code PEAR2 PHP

Mon Oct 28, 2013 12:50 pm

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 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 "<table align='center' border='1' id='natlist' bordercolor='black' class='tablesorter'><form action='' method='POST'>";
echo "<thead><tr bgcolor='#D8D8D8'><th align=left size=3>Nombre</th><th align=left size=3>Servicio</th><th size=3>Tiempo Activo</th><th align=left size=3>Direccion</th><th align=left size=3>Reiniciar</th></tr></thead><tbody>";

//Actualizar pagina
//echo "<meta http-equiv='refresh' content='30'>";


$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 "<tr>";
  echo "<td>". $ppp('name') ."</td>";
  echo "<td>" . $service . "</td>";
  echo "<td>" . $ppp('uptime'). "</td>";
  echo "<td>". $ppp('address') ."</td>"; 
  echo "<td><button type='submit' value='{$id}' name='act[remove]' >Reiniciar</td></tr>";
} 

echo  "</form></tbody></table>";

?>
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Oct 28, 2013 6:31 pm

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.
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Oct 28, 2013 6:47 pm

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
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Oct 28, 2013 7:13 pm

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.
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Nov 11, 2013 9:47 am

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 code

<?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 "<tr>";
  echo "<td>" . src ($ip1) . "</td>"; //Cabecera
  echo "<td>" . $ppp('name') . "</td>"; //Nombre
  echo "<td>" . $service . "</td>"; //Servicio
  echo "<td>" . router($ppp ('caller-id')) . "</td>"; //MAC
  echo "<td>" . $ppp('uptime') . "</td>"; //Tiempo activo
  echo "<td>" . $ppp('address') . "</td>";  //Direccion
  
  //Boton para Reiniciar la conexion activa
  echo "<td>
			<button type='submit' value='{$id}' name='act[remove]'>Reiniciar</button> 
		</td> 
	</tr>";
} 
?>


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

Now, i need print all active routers, and ignore the disable routers :S
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Nov 11, 2013 12:04 pm

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 code

<?php
        try {
            $client = new RouterOS\Client($ip, 'vito', 'vito');
        } catch (Exception $e) 
			{
        ?><div>Imposible Conectarse a <?php echo $ip?></div>
    <?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?
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Nov 11, 2013 4:54 pm

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
          }
}
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Mon Nov 11, 2013 5:36 pm

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 :)

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

php code

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8">
        <title>Listado ByWifi</title>
		<style type="text/css" title="currentStyle">
			@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 }
		</style>
</head>
		
<body>

<?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 '<div><ul>';
						foreach ($errors as $error) 
						{
							echo '<li>' . $error('message') . '</li>';
						}
					echo '</ul></div>';
					}
			}
		}
	}

//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';
}
}

	
?>
<!--Divs para el diseño y organizacion de la tabla-->
	<body id="dt_example">
		<div id="container">
			<div id="demo">
				<div id="tabs">			
					<div id="tabs-1">
<!--Formulario del listado NAT-->
<form action='' method='POST'>

<!--HTML de la Tabla, encabezado -->
<table cellpadding="0" cellspacing="0" border="0" class="display" id="tabla1">
<thead><tr>
<th>Cabecera</th>
<th>Nombre</th>
<th>Servicio</th>
<th>Modelo</th>
<th>Tiempo Activo</th>
<th>Direccion</th>
<th>Reiniciar</th>
</tr></thead><tbody>

<?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 "<tr>";
  echo "<td>" . src ($router[0]) . "</td>"; //Cabecera
  echo "<td>" . $ppp('name') . "</td>"; //Nombre
  echo "<td>" . $service . "</td>"; //Servicio
  echo "<td>" . router($ppp ('caller-id')) . "</td>"; //MAC
  echo "<td>" . $ppp('uptime') . "</td>"; //Tiempo activo
  echo "<td>" . $ppp('address') . "</td>";  //Direccion
  
  //Boton para Reiniciar la conexion activa
  echo "<td>
			<button type='submit' value='{$id}' name='act[remove]'>Reiniciar</button> 
		</td> 
	</tr>";
} 
        } catch (Exception $e)
          {
        ?><div>Imposible Conectarse a <?php echo $router[0];?></div>
    <?php
          }
}
?>

	
</tbody></table></form>

					</div>
				</div>
			</div>
		</div>		
 <!--jQuerys DATATABLE // Llamada a todos los javascripts necesarios-->
        <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>
</html>
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..
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Tue Nov 12, 2013 12:53 am

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.
 
User avatar
Vyrtu
newbie
Topic Author
Posts: 45
Joined: Thu Oct 03, 2013 11:49 am
Location: Torrelavega,Spain

Re: Print ppps from 2 Router Mikrotik in same code PEAR2 PH

Tue Nov 12, 2013 9:52 am

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 }

php code

} catch (Exception $e)
          {
        ?>

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

    <?php
          }
}
?>