Mikrotik

Подключение исполнительных устройств, датчиков, контроллеров.

Модератор: immortal

Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Mikrotik CAPs 2 провайдера Виджет Таблица устройств

Сообщение Bagir »

Предлагаю свой вариант работы с сетью микротиков. Всё это очень уникально, так что просто скопировать не получится. Берите куски кода, или разбирайтесь что к чему. Постараюсь снабдить комментариями. Советую блок кода двух провайдеров и настройку микротика оставьте на потом. Этот момент очень сильно зависит от вашей текущей настройки микротика.


Моя сеть
Несколько микротиков в режиме Caps-Man. Все обращения будут к главному.
Если у вас только один микротик и Caps-Man не используется, то в сценарии можно указать другую таблицу с WiFi устройствами роутера, закомментировать блок кода получения CAPs точек, и не добавлять класс WiFiCaps
2 провайдера Ростелеком и Билайн. Оба провайдера активные. Основной BL, если недоступен, то Интернет будет через РТ.
Если у вас только один провайдер, закомментируйте блок кода в сценарии. Связи с классами по этому моменту никакой нет.


Классы
Во вложении классы WiFiDevice и WiFiCaps. Код в общих методах классов только сообщает о приходе и уходе устройств из сети. Конкретные действия прописываются в личном коде устройства. Пример будет ниже.


Сценарий опроса Микротика
getWiFiclients это главный сценарий который периодически опрашивает Микротик, записывает данные в объекты классов WiFiDevice и WiFiCaps, и вызывает их методы. getWiFiclients вызывает сам себя каждые 10 секунд по средствам функции setTimeOut. Но его нужно запустить, и поддерживать в работе. Добавьте в метод onNewMinute класса Timer код

Код: Выделить всё

setTimeOut('getWiFiclientsTimer',"runScript('getWiFiclients');",10);
сценарий getWiFiclients для опроса микротикаSPOILER_SHOW

Код: Выделить всё

$ip = gg('Mikrotik_IP');
$login = gg('Mikrotik_login');
$password = gg('Mikrotik_password');

// ВНИМАНИЕ на имя класса в вашем файле routeros_api.class.php (в самом начале) 
//$API = new routerosAPI();
$API = new routeros_api();

if ($API->connect($ip, $login, $password)) {

/* ******************************************************************** */ 
 // Получить все объекты класса WiFiDevice
 $objects = getObjectsByClass('WiFiDevice'); 

 // При работе в режиме CAPsMAN все клиенты находятся в таблице /caps-man/registration-table/print
 $ARRAY = $API->comm('/caps-man/registration-table/print');
  
 // перебор объектов класса WiFiDevice
 foreach ($objects as $obj) {
  $obj=getObject($obj['TITLE']);
  $f=0;
  
  // перебор массива роутера 
  foreach ($ARRAY as $i => $arr) {
   if ($obj->getProperty('MAC') == $arr['mac-address']) {
    //$obj->setProperty('lastActive' , date("Y-m-d H:i:s",time()));
    
    // Вызов метода CAPchange, если предыдущая точка была другая, не было вовсе,
    // и устройство было online.
    // Этот метод будет вызван первым. Ранее  Found и Located
    if ($obj->getProperty('CAPname') != $arr['interface']) {
     // ToThink Имя старой точки можно передавать параметром через метод CAPchange.
     //         Тогда в методе будет возможность увидеть имя старой и новой точки.
     //         может быть полезным при реализации условия перехода именно с конкретной точки на нужную
     $oldCAPName = $obj->getProperty('CAPname');
     $obj->setProperty('CAPname', $arr['interface']);
     if ($obj->getProperty('online')) {
      $obj->callMethod('CAPchange', array('oldCAPName' => $oldCAPName));  //ToTest
     }
     unset($oldCapName);
    }

    // Вызов метода Found если устройство не было onLine
    // В данный момент точка доступа в объекте уже записана новая
    if (!$obj->getProperty('online')) {
     $j=$obj->getProperty('holdCycles');
     if (!$j) { $j=1; }
     $obj->setProperty('online', $j); 
     unset($j);
     $obj->callMethod('Found');
    }
    
    // Вызов метода Located каждый раз при опросе и присутствии девайса в сети
    // будет использоваться например для продления активности в комнате
    // в данный момент в объекте записана новая точка доступа
    $obj->callMethod('Located');
    $obj->setProperty('lastActive' , date("Y-m-d H:i:s",time()));
    
    // удаляем элемент массива
    unset($ARRAY[$i]);
    $f=1;
    // break; 
   }
  }
 
  // если MAC этого объекта в массиве роутера нет
  // Уменьшить свойство online. Когда достигнет нуля, вызвать метод Lost
  if (!$f) {
   $j=$obj->getProperty('online');
   if ($j) {
    $j=$j-1;
    $obj->setProperty('online', $j); 
    // Вызов метода Lost
    if (!$j) { $obj->callMethod('Lost'); }
   }
   unset($j);
  } 
 
 }

 
 // перебор оставшихся MAC адресов массива роутера
 foreach ($ARRAY as $arr) {
  // Создание нового объекта
  say('Зарегистрировано новое ВайФай устройство.');
  addClassObject('WiFiDevice', 'wifi_'.$arr['mac-address']);
  $obj=getObject('wifi_'.$arr['mac-address']);
  $obj->setProperty('MAC', $arr['mac-address']); 
  $obj->setProperty('CAPname', $arr['interface']);
  //$obj->setProperty('name', 'Неизвестный девайс'); 
  $obj->setProperty('lastActive' , date("Y-m-d H:i:s",time()));
  $obj->setProperty('notify' , '20');
  $obj->setProperty('online', '1');
  $obj->setProperty('holdCycles', '2'); 
  $obj->callMethod('Found');
 } 

 
/* ******************************************************************** */ 
 // Получить все объекты класса WiFi точек доступа
 $objects = getObjectsByClass('WiFiCaps'); 

 // таблица роутера с точками доступа
 $ARRAY = $API->comm('/caps-man/interface/print');

 // перебор объектов класса WiFiCaps
 foreach ($objects as $obj) {
  $obj=getObject($obj['TITLE']);
  
  // перебор массива роутера 
  foreach ($ARRAY as $i => $arr) {
   if ($obj->object_title == $arr['name']) {
    
    if ($obj->getProperty('MAC') != $arr['mac-address']) {
     $obj->setProperty('MAC', $arr['mac-address']);
    }

    // Основной показатель работоспособности точки
    // свидетельствует о наличии линка у точки с главным
    if ($obj->getProperty('bound') != $arr['bound']) {
     $obj->setProperty('bound', $arr['bound']);
     // Вызов метода
     if ($arr['bound']=='true') {
      $obj->callMethod('Found');
     } else {
      $obj->callMethod('Lost');
     }
    }

    if ($obj->getProperty('inactive') != $arr['inactive']) {
     $obj->setProperty('inactive', $arr['inactive']);
     //$obj->callMethod('');
    }

    if ($obj->getProperty('running') != $arr['running']) {
     $obj->setProperty('running', $arr['running']);
     //$obj->callMethod('');
    }

    if ($obj->getProperty('disabled') != $arr['disabled']) {
     $obj->setProperty('disabled', $arr['disabled']);
     //$obj->callMethod('');
    }

    // удаляем элемент массива
    unset($ARRAY[$i]);

   } // имена равны
  } // массив роутера
 } // объекты класса

 
 // перебор оставшихся элементов массива роутера
 foreach ($ARRAY as $arr) {
  // Создание нового объекта
  say('Зарегистрирована новая точка доступа '.$arr['name']);
  addClassObject('WiFiCaps', $arr['name']);
  $obj=getObject($arr['name']);
  $obj->setProperty('MAC', $arr['mac-address']); 
  $obj->setProperty('bound', $arr['bound']); 
  $obj->setProperty('inactive', $arr['inactive']); 
  $obj->setProperty('running', $arr['running']); 
  $obj->setProperty('disabled', $arr['disabled']); 
  // $obj->callMethod('Found');
 }

/* ******************************************************************** */ 
 // Контроль состояния провайдеров
 // 0-нет линка 1-линк с провайдером 2-есть Интернет 3-выбран основным
 $isp1=0; $isp2=0;
 // пинг до микротиковского облака
 $isp1png=''; $isp2png='';

 /* Узнаем о наличии линка и Интернета за провайдером с помощью Detect Internet
     ВНИМАНИЕ замените имена интерфейсов на свои
     нужно активировать Detect Internet Для интерфейсов провайдеров.
     Я сделал лист wan, и добавил в него провайдеров. Detect Internet смотрит на лист wan
 */    
 $ARRAY = $API->comm('/interface/detect-internet/state/print');
 // перебор массива роутера 
 foreach ($ARRAY as $i => $arr) {
  switch ($arr['state']) {
   // Интернет за провайдером
   case 'internet':
    if ($arr['name']=='pppoe-out1') { $isp1=2; $isp1png=$arr['cloud-rtt']; }
    if ($arr['name']=='ether9') { $isp2=2; $isp2png=$arr['cloud-rtt']; }
    break;
   // провайдер доступен
   case 'wan':
   case 'lan':
    if ($arr['name']=='pppoe-out1') { $isp1=1; }
    if ($arr['name']=='ether9') { $isp2=1; }
    break;
   // нет линка с провайдером
   case 'no-link':
   default: 
    if ($arr['name']=='pppoe-out1') { $isp1=0; }
    if ($arr['name']=='ether9') { $isp2=0; }
 }}
 // пинги до м.облока
 sg('isp1ping',$isp1png);
 sg('isp2ping',$isp2png);

 
 // таблица роутера ip route print detail
 $ARRAY = $API->comm('/ip/route/print');
 /* перебор массива роутера в поисках основного провайдера
     ВНИМАНИЕ замените id *1D и *1E на свои
     Независимо от способа переключения провайдеров,
     у вас в итоге должны быть два маршрута на разных провайдеров. 
     Один в данный момент активный, второй нет 
     при желании id записей можно заменить на уникальные комментарии
 */
 foreach ($ARRAY as $i => $arr) {
  if ($arr['active']=='true') {
   switch ($arr['.id']) {
    case '*1D':
     $isp1=max($isp1,3);
     break;
    case '*1E':
     $isp2=max($isp2,3);
     break;
 }}}    

 
 $pisp=gg('isp1');
 $isp=$isp1;
 $t='';
 if ($pisp<>$isp) {
  $p='Ростелеком';
  if ($isp==0) {$t="Потеря соединения c провайдером $p";}
  elseif ($isp==1 && $pisp==0) {$t="Установлено соединения c провайдером $p";}
  elseif ($isp==1 && $pisp>=2) {$t="Провайдер $p не предоставляет Интернет";}
  elseif ($isp==2 && $pisp<=1) {$t="Провайдер $p, Интернет предоставлен";}
  elseif ($isp==3) {$t="Провайдер $p выбран основным";}
  sg('isp1',$isp1);
  if ($t) { say($t); }
 }

 $pisp=gg('isp2');
 $isp=$isp2;
 $t='';
 if ($pisp<>$isp) {
  $p='Бинайн';
  if ($isp==0) {$t="Потеря соединения c провайдером $p";}
  elseif ($isp==1 && $pisp==0) {$t="Установлено соединения c провайдером $p";}
  elseif ($isp==1 && $pisp>=2) {$t="Провайдер $p не предоставляет Интернет";}
  elseif ($isp==2 && $pisp<=1) {$t="Провайдер $p, Интернет предоставлен";}
  elseif ($isp==3) {$t="Провайдер $p выбран основным";}
  sg('isp2',$isp2);
  if ($t) { say($t); }
 }

/* ******************************************************************** */ 
 
  $API->disconnect();
  echo 'getWiFiclients ok'; 
  setTimeOut('getWiFiclientsTimer',"runScript('getWiFiclients');",10);
 
} else { echo 'error'; }

Альтернативный вариант с использованием цикла
Во вложении есть файл cycle_microtik. Распакуйте его и положите в папку scripts где лежат все файлы циклов. При этом уберите все точки запуска сценария getWiFiclients, например в метод onNewMinute класса Timer. Сам сценарий getWiFiclients тоже при этом не нужен. Весь его код находится в файле cycle_microtik. Исправьте id и имена интерфейсов на свои. Запустите цикл cycle_microtik из X-Ray -> Services, или перезапустите все циклы.
В данном случае плюсы цикла перед сценарием:
- логинимся в микротике только один раз, а не каждый запуск сценария;
- код выполняется в отдельном процессе и не мешает системе;
- при неудачном обращении к микротику, следующая попытка идет с задержкой.
- время чтения можно увеличить. Мне хватает каждые 10 секунд, но легко можно и чаще;
- не используем таймеры для частого запуска сценария;
- меньше действий в системе, и меньше кода в разных модулях.


В объекте ThisComputer должны быть свойства Mikrotik_login, Mikrotik_password; и будут свойства isp1, isp2, isp1png, isp2png
в isp-ы будет записан статус провайдеров. 0-не активен 1-активен 2-есть интернет 3-выбран основным
в isp_png - пинги до микротиковского облака. Они выводятся на виджете.
Для получения этих данных, в сценарии нужно указать имена интерфейсов провайдеров и id их маршрутов в таблице routes.
Внимание на имя класса routeros_api. Ранее у меня было routerosAPI. файл скачивал от сюда https://yadi.sk/d/W3PkbOjY3OXzzQ
Положил его в .../Lib/ Чтобы класс роутера был доступен везде, и не делать require перед обращением к классу.

Отдельно стоит упомянуть про свойства объектов класса WiFiDevice:
notify - При каких событиях уведомлять
0-нет, 1-днем, 2-всегда, иначе не писать в чате. 1 цифра пришел, 2 ушел, 3 смена точки.
например 210 будет означать, что говорить всегда при появлении девайса в сети, говорить только днем при уходе, и вообще не говорить при смене точки. Только днем или всегда зависит от приоритетов функции say() вашей системы.
holdCycles - Количество циклов удержания и
online - в сети, где 0 - не в сети, а любая цифра - в сети.
Некоторые устройства периодически выключают свой wifi модуль для экономии энергии. В таких случаях следует установить holdCycles побольше. Каждое выполнение сценария getWiFiclients будет понижать свойство online на единицу, пока оно не станет =0. При появлении устройства online будет установлено = holdCycles. Так что при больших значениях holdCycles устройство ещё "будет в сети" какое то время.

Обнаруженные WiFi устройства будут добавлены в класс WiFiDevice
Точки Caps в класс WiFiCaps
Так же сценарий вызовет соответствующие методы классов при появлении и ухода устройств из сети.

Для работы сценария понадобится дополнительный сценарий переопределения имени точки на дружественное. Исправьте имена точек на свои. Задача CAPsFriendlyName только в назначении дружественного имени точке. Причем в двух падежах. CAPsFriendlyName работает как функция. Мы ей имя точки как в микротике, а она нам массив дружественных имен из двух падежей.
CAPsFriendlyNameSPOILER_SHOW

Код: Выделить всё

/* Возвращает дружественное имя точек доступа WiFi */

$s=$params['name'];
if (isset($s)) {
 switch($s) {
  case 'CAP--Bagir-1':  $a[0]='Кабинет'; $a[1]='в кабинете'; break;
  case 'CAP--BagirS-1': $a[0]='Крыльцо'; $a[1]='на крыльце'; break;
  case 'CAP--SXT-1': $a[0]='Двор'; $a[1]='во дворе'; break;
  case 'CAP--hAPmini-1': $a[0]='Кухня'; $a[1]='на кухне'; break;
  case 'CAP--alikey-1': $a[0]='Громоотвод'; $a[1]='на громоотводе'; break;
  default: $a[0]=$s; $a[1]=$s;
 }
} else { $a[0]='Сетевое имя точки не передано'; $a[1]=$a[0];} 
   
return $a;

Домашняя страница с таблицей устройств
Нам будет нужно посмотреть, какие устройства сейчас в сети, и какие были совсем недавно.
Таблица.png
Таблица.png (14.43 КБ) 4449 просмотров
Для этого создадим домашнюю страницу с типом Ссылка, которая будет запускать скрипт для составления таблицы.
В настройках страницы:
Ссылка: http://localhost/objects/?script=wifiTable&print=1
исправьте адрес сервера на свой
Сценарий wifiTableSPOILER_SHOW

Код: Выделить всё

$now = new DateTime(); // текущее время на сервере
$date1 = $now->modify('-1 hour'); // старше часа будут серые
$f=0; // флаг наличия первых данных для начала таблицы
 
// >WiFi устройства onLine
$objects=getObjectsByClass('WiFiDevice');
foreach($objects as $obj) {
  $obj=getObject($obj['TITLE']);
  $ol = $obj->getProperty('online');
  // Дата последней активности
  $dateol = DateTime::createFromFormat("Y-m-d H:i:s", $obj->getProperty('lastActive')); // дату в дату

  if ($ol || $date1 < $dateol ) {
      // При первом найденном открываем раздел и таблицу
      if (!$f) { 
       // Имя таблицы      
       echo '<br /><details open><summary><big><b  style="color:#ff0000">WiFi устройства onLine</b></big></summary> <blockquote>';
       echo '<table border="1">';
       
       // Заголовок таблицы      
       echo '<tr>';
       echo '<th>MAC</th>';
       echo '<th>Устройство</th>';
       echo '<th>Владелец</th>';
       echo '<th>CAPs name</th>';
       echo '<th>Имя точки</th>';
      echo '</tr>';

      $f=1;
    }
    $no=$obj->getProperty('CAPname');
    // переопределить имя точки. [0] имя [1] где
    $nf=runscript('CAPsFriendlyName',array('name'=>$no))[0];

    // Разный цвет текста
    if (!$ol)              { $cn='<font color="gray">'; $ce='</font>'; } else { $cn=''; $ce=''; }
   
    // Напечатать имена и описание объектов
    echo '<tr>';
    echo '<td>'.$cn.$obj->getProperty('MAC').$ce.'</td>';
    echo '<td>'.$cn.$obj->getProperty('deviceName').'</td>'.$ce;
    echo '<td>'.$cn.$obj->getProperty('owner').$ce.'</td>';
    echo '<td>'.$cn.$no.$ce.'</td>';
    echo '<td>'.$cn.$nf.$ce.'</td>';
    echo '</tr>';

  }
}
// Закрываем таблицу 
if ( $f ) { echo '</table></blockquote></details>'; }
$f=0;



// >WiFi точки доступа
$objects=getObjectsByClass('WiFiCaps');
foreach($objects as $obj) {
    $obj=getObject($obj['TITLE']);
    // При первом найденном открываем раздел и таблицу
    if (!$f) { 
      // Имя таблицы      
      echo '<br /><details open><summary><big><b  style="color:#ff0000">WiFi точки доступа</b></big></summary> <blockquote>';
      echo '<table border="1">';
       
      // Заголовок таблицы      
      echo '<tr>';
      echo '<th>Имя точки</th>';
      echo '<th>MAC</th>';
      echo '<th><p title="bound">Связь</p></th>';
      echo '<th><p title="inactive">Отключена</p></th>';
      echo '<th><p title="running">Клиенты</p></th>';
      echo '<th><p title="disabled">Запрещена</p></th>';
      echo '</tr>';

      $f=1;
    }

    // Напечатать имена и описание объектов
    echo '<tr>';
    echo '<td>'.$obj->object_title.'</td>';
    echo '<td>'.$obj->getProperty('MAC').'</td>';
    if ($obj->getProperty('bound') == 'true' ) {$t='&bull;';} else {$t=' ';}     echo '<td align="center" style="color:#008000"><big>'.$t.'</big></td>';
    if ($obj->getProperty('inactive') == 'true' ) {$t='&bull;';} else {$t=' ';}  echo '<td align="center" style="color:#ff0000"><big>'.$t.'</big></td>';
    if ($obj->getProperty('running') == 'true' ) {$t='&bull;';} else {$t=' ';}   echo '<td align="center" style="color:#000080"><big>'.$t.'</big></td>';
    if ($obj->getProperty('disabled') == 'true' ) {$t='&bull;';} else {$t=' ';}  echo '<td align="center" style="color:#ff0000"><big>'.$t.'</big></td>';
    echo '</tr>';
  
}
// Закрываем таблицу 
if ( $f) { echo '</table></blockquote></details>'; }
$f=0;

Красивый элемент на сцене
Интернет.png
Интернет.png (18.61 КБ) 4278 просмотров
Дополнительный код CSSSPOILER_SHOW

Код: Выделить всё

div.element_164 {
  border-radius:10px;
  padding:5px;
  width:120px;
  height:120px;
  background: linear-gradient(135deg, rgba(100,160,220,1) 1%,rgba(170,230,280,1) 100%);
}
не забудьте исправить element_164 на свой!
html код элементаSPOILER_SHOW

Код: Выделить всё

<svg width="100%" height="100%">
 
 <!-- Облако -->
 <g transform="translate(27.5, 0)" >
  <g transform="scale(1.2) translate(-3, -3)" >
   <path style="fill:linen;stroke:#45413C;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M47.2,18.6c0-2-1.4-3.7-3.3-4.1c0-0.2,0.1-0.4,0.1-0.6c0-2.3-1.9-4.2-4.2-4.2      c-0.9,0-1.7,0.3-2.4,0.7c0-0.1,0-0.2,0-0.3c0-2.3-1.9-4.2-4.2-4.2c-1.2,0-2.2,0.5-3,1.2c-0.5-1.8-2.1-3.1-4.1-3.1      s-3.6,1.3-4.1,3.1c-0.8-0.8-1.8-1.2-3-1.2c-2.3,0-4.2,1.9-4.2,4.2c0,0.1,0,0.2,0,0.3c-0.7-0.5-1.5-0.7-2.4-0.7      c-2.3,0-4.2,1.9-4.2,4.2c0,0.2,0,0.4,0.1,0.6C6.4,14.9,5,16.6,5,18.6c0,2.1,1.5,3.8,3.6,4.2c-0.2,0.5-0.3,1-0.3,1.5      c0,2.3,1.9,4.2,4.2,4.2c0.9,0,1.7-0.3,2.4-0.7c0,0.1,0,0.2,0,0.3c0,2.3,1.9,4.2,4.2,4.2c1.3,0,2.4-0.6,3.2-1.5      c0.7,1.4,2.1,2.5,3.8,2.5c1.7,0,3.2-1,3.8-2.5c0.8,0.9,1.9,1.5,3.2,1.5c2.3,0,4.2-1.9,4.2-4.2c0-0.1,0-0.2,0-0.3      c0.7,0.5,1.5,0.7,2.4,0.7c2.3,0,4.2-1.9,4.2-4.2c0-0.5-0.1-1-0.3-1.5C45.7,22.5,47.2,20.7,47.2,18.6z"/> 
   <path fill="#FFD0E0" d="M44.9,17c0.2,0.5,0.3,1,0.3,1.6c0,2.5-2,4.5-4.5,4.5c-0.9,0-1.8-0.3-2.5-0.8      c0,0.1,0,0.2,0,0.3c0,2.5-2,4.5-4.5,4.5c-1.4,0-2.6-0.6-3.4-1.6c-0.7,1.5-2.3,2.6-4.1,2.6S22.7,27,22,25.4c-0.8,1-2,1.6-3.4,1.6      c-2.5,0-4.5-2-4.5-4.5c0-0.1,0-0.2,0-0.3c-0.7,0.5-1.6,0.8-2.5,0.8c-2.5,0-4.5-2-4.5-4.5c0-0.6,0.1-1.1,0.3-1.6      c-0.6-0.1-1.2-0.3-1.7-0.7C5.2,17,5,17.8,5,18.6c0,2.1,1.5,3.8,3.6,4.2c-0.2,0.5-0.3,1-0.3,1.5c0,2.3,1.9,4.2,4.2,4.2      c0.9,0,1.7-0.3,2.4-0.7c0,0.1,0,0.2,0,0.3c0,2.3,1.9,4.2,4.2,4.2c1.3,0,2.4-0.6,3.2-1.5c0.7,1.4,2.1,2.5,3.8,2.5      c1.7,0,3.2-1,3.8-2.5c0.8,0.9,1.9,1.5,3.2,1.5c2.3,0,4.2-1.9,4.2-4.2c0-0.1,0-0.2,0-0.3c0.7,0.5,1.5,0.7,2.4,0.7      c2.3,0,4.2-1.9,4.2-4.2c0-0.5-0.1-1-0.3-1.5c2-0.3,3.6-2.1,3.6-4.2c0-0.8-0.3-1.6-0.7-2.3C46,16.6,45.5,16.9,44.9,17z"/>
  </g>
  <text x="10" y="22" fill="black" stroke="none" font-size="10px">Internet</text>
 </g>

 
 <!-- Провайдер RT -->
 <g transform="translate(0, 51.3)" onClick='runScript("isp1select");'>
    <g transform="scale(0.6) translate(-291 -732) matrix(.10273 0 0 .10273 282.24 709.45)">
      <g stroke="none">
        <path fill='%ThisComputer.isp1|"rgb(50%, 50%, 50%);rgb(80%, 80%, 0%);rgb(0%, 50%, 0%);rgb(27%, 31%, 70%)"%' d="m95.37 339.97 241.06 113.64 245.89-115.92-241.06-113.64z"/>
        <path fill='%ThisComputer.isp1|"rgb(60%, 60%, 60%);rgb(90%, 90%, 10%);rgb(10%, 60%, 10%);rgb(36%, 40%, 80%)"%' d="m336.43 453.61v141.21l245.89-115.92v-141.21z"/>
        <path fill='%ThisComputer.isp1|"rgb(70%, 70%, 70%);rgb(100%, 100%, 20%);rgb(20%, 70%, 20%);rgb(48%, 48%, 90%)"%' d="m95.37 339.97 241.06 113.64v141.21l-241.06-113.65z"/>
      </g>
      <g fill="#f0f0f0">
        <path d="m302.68 264.66 38.514 5.6218 38.514 5.6218-16.367 5.3307 40.055 21.107-26.52 10.44-44.055-21.607-16.367 5.3308-6.8691-15.929z"/>
        <path d="m473.91 375.32-6.8691-15.929-6.8691-15.929-16.367 5.3308-46.555-22.107-26.02 9.9405 42.055 22.107-16.367 5.3307 38.514 5.6218z"/>
        <path d="m218.1 303.03 38.514 5.6218 38.514 5.6218-16.367 5.3307 41.555 21.107-25.52 10.94-46.555-22.107-16.367 5.3308-6.8691-15.929z"/>
        <path d="m391.74 411.85-6.8691-15.929-6.8691-15.929-16.367 5.3308-46.555-22.107-26.52 9.9405 42.555 22.107-16.367 5.3307 38.514 5.6218z"/>
      </g>
    </g>
    <text x="0" y="0" fill="black" stroke="none" font-size="10px">RT</text>
    <text x="0" y="-10" fill="black" stroke="none" font-size="10px">%ThisComputer.isp1ping%</text>
 </g>

 <!-- Провайдер BL -->
 <g transform="translate(79, 51.3)" onClick='runScript("isp2select");'>
    <g transform="scale(0.6) translate(-291 -732) matrix(.10273 0 0 .10273 282.24 709.45)">
      <g stroke="none">                <!-- gray;yellow;green;blue -->
        <path fill='%ThisComputer.isp2|"rgb(50%, 50%, 50%);rgb(80%, 80%, 0%);rgb(0%, 50%, 0%);rgb(27%, 31%, 70%)"%' d="m95.37 339.97 241.06 113.64 245.89-115.92-241.06-113.64z"/>
        <path fill='%ThisComputer.isp2|"rgb(60%, 60%, 60%);rgb(90%, 90%, 10%);rgb(10%, 60%, 10%);rgb(36%, 40%, 80%)"%' d="m336.43 453.61v141.21l245.89-115.92v-141.21z"/>
        <path fill='%ThisComputer.isp2|"rgb(70%, 70%, 70%);rgb(100%, 100%, 20%);rgb(20%, 70%, 20%);rgb(48%, 48%, 90%)"%' d="m95.37 339.97 241.06 113.64v141.21l-241.06-113.65z"/>
      </g>
      <g fill="#f0f0f0">
        <path d="m302.68 264.66 38.514 5.6218 38.514 5.6218-16.367 5.3307 40.055 21.107-26.52 10.44-44.055-21.607-16.367 5.3308-6.8691-15.929z"/>
        <path d="m473.91 375.32-6.8691-15.929-6.8691-15.929-16.367 5.3308-46.555-22.107-26.02 9.9405 42.055 22.107-16.367 5.3307 38.514 5.6218z"/>
        <path d="m218.1 303.03 38.514 5.6218 38.514 5.6218-16.367 5.3307 41.555 21.107-25.52 10.94-46.555-22.107-16.367 5.3308-6.8691-15.929z"/>
        <path d="m391.74 411.85-6.8691-15.929-6.8691-15.929-16.367 5.3308-46.555-22.107-26.52 9.9405 42.555 22.107-16.367 5.3307 38.514 5.6218z"/>
      </g>
    </g>
    <text x="20" y="0" fill="black" stroke="none" font-size="10px">BL</text>
    <text x="5" y="-10" fill="black" stroke="none" font-size="10px">%ThisComputer.isp2ping%</text>
 </g>

 <!-- Роутер -->
 <g transform="translate(39.5, 89) scale(0.1)" onClick='runScript("getWiFiclients");'>
  <defs>
    <linearGradient x1="0.65625" y1="125.12147" x2="299.9375" y2="125.12147" id="linearGradient3833" gradientUnits="userSpaceOnUse" gradientTransform="translate(-0.31342216,851.86901)">
      <stop id="stop3780" style="stop-color:#557b8b;stop-opacity:1" offset="0"/>
      <stop id="stop3617" style="stop-color:#8aaac0;stop-opacity:1" offset="1"/>
    </linearGradient>
  </defs>
   <g transform="translate(5,-848)">
        <path d="m 0.34282784,901.90026 0,100.62504 0.03125,0 c 0.13323192,17.103 26.93452416,33.7389 74.81249916,42.9062 71.558743,13.7016 163.060593,5.5444 204.375003,-18.1875 13.59024,-7.8065 20.05029,-16.3087 20.0625,-24.7187 l 0,-100.37504 c -0.0444,8.38955 -6.50621,16.86923 -20.0625,24.65625 C 238.24717,950.53839 146.74532,958.66433 75.186577,944.96276 27.137451,935.76265 0.31623817,919.06779 0.37407784,901.90026 l -0.03125,0 z" style="fill:url(#linearGradient3833);fill-opacity:1;stroke:none"/>
        <path d="m 280.43717,678.68689 a 113.47587,113.47587 0 1 1 -226.951735,0 113.47587,113.47587 0 1 1 226.951735,0 z" transform="matrix(1.141816,0.218627,-0.659227,0.378674,406.7696,608.8589)" style="fill:#557b8b;fill-opacity:1;stroke:none"/>
        <path d="m 229.92724,898.48426 -18.78401,10.78993 66.58103,12.7485 -12.52268,7.1933 -66.58103,-12.7485 -18.78403,10.7899 -12.48521,-21.5727 62.57593,-7.20043 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
        <path d="m 120.16224,877.46718 -18.78403,10.78992 -66.581031,-12.7485 -12.52268,7.19328 66.581041,12.7485 -18.78402,10.78991 62.57593,-7.20044 -12.48521,-21.57267 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
        <path d="m 136.24453,936.84279 -26.02789,-4.9836 38.44057,-22.0811 -17.35193,-3.3224 -38.44058,22.0811 -26.0279,-4.9837 13.03556,19.0916 56.37217,-5.8019 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
        <path d="m 233.16085,881.17199 -26.0279,-4.98365 -38.43962,22.08051 -17.35193,-3.32244 38.43961,-22.0805 -26.0279,-4.98366 56.37312,-5.80238 13.03462,19.09212 z" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"/>
   </g>
 </g>

 <!-- Крестики для линий -->
 <defs>
  <g id="krest8549">
   <line x1="10" y1="5" x2="10" y2="15" stroke="red" />
   <line x1="5" y1="10" x2="15" y2="10" stroke="red" />
  </g>
 </defs>

 <!-- От провайдера в Интернет -->
 <g transform="translate(20, 33)" >
  <line x1="20" y1="0" x2="0" y2="20" stroke="black" />
  <use href="#krest8549" style='display:%ThisComputer.isp1|"block;block;none;none"%'/>
 </g>
 <g transform="translate(70, 33)" >
  <line x1="0" y1="0" x2="20" y2="20" stroke="black" />
  <use href="#krest8549" style='display:%ThisComputer.isp2|"block;block;none;none"%'/>
 </g>

 <!-- От роутера к провайдеру -->
 <g transform="translate(20, 73)" >
  <line x1="0" y1="0" x2="20" y2="20" stroke="black" />
  <use href="#krest8549" style='display:%ThisComputer.isp1|"block;none;none;none"%'/>
 </g>
 <g transform="translate(70, 73)" >
  <line x1="20" y1="0" x2="0" y2="20" stroke="black" />
  <use href="#krest8549" style='display:%ThisComputer.isp2|"block;none;none;none"%'/>
 </g>

</svg>
Все элементы выполнены на svg, можете раздербанить на запчасти. В коде всё сделано группами
Цвет провайдеров будет меняться в зависимости от значений свойств isp1 и isp2.
На линиях будут крестики при неактивном провайдере и отсутствии Интернета за ним.
К примеру у меня сейчас активны оба провайдера, у обоих есть Интернет, и второй выбран основным.
При нажатии на провайдеров вызывается скрипт runScript("isp1select"); и runScript("isp2select");
Скрипт меняет дистанцию провайдера. Так можно быстро выбрать основным провайдером другого, если на то есть необходимость.
У меня у isp2 дистанция всегда 20. У isp2 cкриптами isp1select меняю на 10, isp2select на 30, тем самым маршрут isp1 встает до или после isp2
скрипт isp1selectSPOILER_SHOW

Код: Выделить всё

$ip = gg('Mikrotik_IP');
$login = gg('Mikrotik_login');
$password = gg('Mikrotik_password');

$API = new routeros_api();
$API->debug = false;
if ($API->connect($ip, $login, $password)) {
 $API->write('/ip/route/set',false);
 $API->write('=.id=*1D',false);
 $API->write('=distance=10');
 $READ = $API->read(false);

$API->disconnect();
 echo 'ok'; 
 
} else { echo 'error'; }
Поменяйте *1D на id своего маршрута. Во втором скрипте так же. Дистанцию тоже укажите согласно вашей настройке.


Пример настройки методов объекта телефона
Объекты.png
Объекты.png (9.1 КБ) 4438 просмотров
МетодыSPOILER_SHOW
Метод CAPchange. Сработает при смене точки. Эта за входной дверью. Когда объект не на охране, Алиса откроет дверь своим.

Код: Выделить всё

switch ($this->getProperty('CAPname')) {
case 'CAP--BagirS-1':
 say('Открываю Серёже входную дверь');
 callMethod(.....................);
 break;
}
Метод Found. Подъехал к дому, точка на фасаде засечет первая. В этом примере включаю свет только при методе Found, т.к.
телефон может сесть на это точку когда уже буду дома.

Код: Выделить всё

switch ($this->getProperty('CAPname')) {
case 'CAP--Bagir-1':
 // Включить прожекторы у подъезда, если телефон обнаружен на этой точке
 cm('DrivewayArea.onActivity');
 break;
case 'CAP--BagirS-1':
 // Открыть дверь
 say('Открываю Серёже входную дверь');
 callMethod('..............');
 break;
}
Метод Located. Нахождение устройства на точке. Не во всех объектах класса Room у меня есть детекторы движения. На некоторых определяю присутствие по WiFi устройствам. Вот пример

Код: Выделить всё

switch ($this->getProperty('CAPname')) {
case 'CAP--SXT-1':
 cm('Gazebo.onActivity');
 break;
case 'CAP--hAPmini-1':
 cm('KitchenArea.onActivity');
 break;
}
Метод Lost. Телефон как радио метка для разрешения подъема гаражных ворот

Код: Выделить всё

callMethod('bs_garageLabel.statusChanged', array('status'=>0));

Где ещё можно использовать
marker - свойство класса WiFiDevice. Поставьте в нем флаг "f" для устройств близких друзей.
Заполните свойства
owner - владелец. Например просто Имя или Имя Фамилия
deviceName - имя устройства. Например Телефон брата или Терминал на кухне.

Добавьте в метод activate объекта GuestsMode класс OperationalModes код

Код: Выделить всё

// перебор объектов класса
$objects=getObjectsByClass("WiFiDevice");
//перебрать объекты класса и собрать массив с именами друзей
foreach($objects as $obj) {
 $obj=getObject($obj['TITLE']);
 // Если online и друг
 if ($obj->getProperty('online')) {
  if (stripos($obj->getProperty('marker'), 'f')!==false) {
   $s=$obj->getProperty('owner');
   if ($s) {
    // взять до пробела (отбросить фамилию)
    $arr[]=explode(' ', $s)[0];
   } else {
    $arr[]='Неизвестный';
   }
 }}
}


$s='У нас гости.';

if (isset($arr)) {
 //Первый элемент массива
 $s.=' '.$arr[0];
 //со второго по предпоследний через запятую 
 for($i = 1, $size = count($arr)-1; $i < $size; ++$i) {
  $s.=', '.$arr[$i];
 }
 // последний через "и"
 if (count($arr) > 1) {
  $s.=' и '.end($arr);
 } 
 // вывод
 //echo $s;
 say($s, (gg('GuardMode.status')>1)?3:2);
}
И получите уведомление кто к вам пришел при активации режима "У нас гости". По аналогии можно добавить любые свои флаги.


Создайте сценарий friendshere

Код: Выделить всё

 // Получить все объекты класса
 $objects = getObjectsByClass('WiFiDevice'); 

 // перебор объектов класса WiFiDevice
 // Поиск первого совпадения. Устройство друга в сети
 foreach ($objects as $obj) {
  $obj=getObject($obj['TITLE']);

  if ($obj->getProperty('online')) {
   if (stripos($obj->getProperty('marker'), 'f') !== false) {
    $f = true;
    break;
   }
  }
 }

 // Решение о изменении состояния режима
 if (gg('GuestsMode.status')) {
  if (!$f) { cm('GuestsMode.deactivate'); }
 } else {
  if ($f) { cm('GuestsMode.activate'); }
 }
И запускайте его, например из методов Found и Lost телефонов своих друзей. Вы получите активацию и деактивацию режима "У нас гости". Лично я пока что не знаю как по другому определять этот режим, кроме как по мобильным телефонам.
Вложения
cycle_microtik.zip
цикл вместо сценария getWiFiclients
(3.47 КБ) 216 скачиваний
WiFiCaps.txt
(2.92 КБ) 235 скачиваний
WiFiDevice.txt
(8.76 КБ) 213 скачиваний
Последний раз редактировалось Bagir Вт июн 23, 2020 12:00 am, всего редактировалось 17 раз.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Maxtor
Сообщения: 13
Зарегистрирован: Сб мар 31, 2018 3:02 pm

Re: Mikrotik

Сообщение Maxtor »

Супер!! Спасибо огромное!!! А свойства и методы есть в WiFiCaps? Так все заработало, единственное с провайдерами еще не разбирался.
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik

Сообщение Bagir »

Maxtor писал(а): Пн июн 15, 2020 4:57 pmсвойства и методы есть в WiFiCaps?
Есть пока только Found и Lost. В общем коде так же только уведомления о включении и выключении точки. Мне помогло обнаружить, что одна точка стала часто перезагружаться. Поменял на ней блок питания и всё норм. Видать отжил своё с годами. В личных методах класса FiWiCaps тоже можно писать свой код. Но я пока не придумал за чем мне это нужно. Мне достаточно только уведомлений пришла / ушла. Все мои точки всегда активны.
Maxtor писал(а): Пн июн 15, 2020 4:57 pmи сценарии
Сценарий getWiFiclients запускается у меня из метода onNewMinute класса Timer. Мне такая периодичность нужна, чтобы пускать домой при нахождении у точки на крыльце. Забыл это написать.

Код: Выделить всё

setTimeOut('getWiFiclientsTimer',"runScript('getWiFiclients');",10);
Затем этот же код в конце сценария перезапускает его через 10 секунд. Он в примере закомментирован. Включите его. Вероятно я что то там экспериментировал, да забыл.
Maxtor писал(а): Пн июн 15, 2020 4:57 pmCAPsFriendlyName и wifiTable
Задача CAPsFriendlyName только в назначении дружественного имени точке. Причем в двух падежах. wifiTable собирает код для домашней страницы. Но она весьма полезная. CAPsFriendlyName работает как функция. Мы ей имя точки как в микротике, а она нам массив дружественных имен из двух падежей.
Maxtor писал(а): Пн июн 15, 2020 4:57 pmв свойствах WiFiClient у меня CAPname Пишет как микротик передает "Cap2.4-Hall-1" я так понял метод CAPsFriendlyName как раз меняет это имя?
Точно так. Там прямо в коде CAPsFriendlyName нужно записать свои имена Cap-сов и придумать им имена в двух падежах.
Maxtor писал(а): Пн июн 15, 2020 4:57 pmс провайдерами еще не разбирался
Тут надо будет добавить настройки в микротик. В таблицу routes. И в сценарии getWiFiclients указать ip адреса провайдеров и id маршрутов. Я немного дописал в начальном топике, в спойлере. Тут можно попробовать всё настроить в отдельном скрипте и потом перенести код в getWiFiclients. Суть я тоже описал в спойлере.
Maxtor писал(а): Пн июн 15, 2020 4:57 pmвсе заработало
Круто! Даже не думал, что так всё хорошо подойдет. Очень рад.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik

Сообщение Bagir »

Maxtor писал(а): Пн июн 15, 2020 4:57 pmА свойства и методы есть в WiFiCaps?
Я наверное понял о чем речь. Вот часть скрипта getWiFiclients

Код: Выделить всё

     // Вызов метода
     if ($arr['bound']=='true') {
      $obj->callMethod('Found');
     } else {
      $obj->callMethod('Lost');
     }
    }

    if ($obj->getProperty('inactive') != $arr['inactive']) {
     $obj->setProperty('inactive', $arr['inactive']);
     //$obj->callMethod('');
    }

    if ($obj->getProperty('running') != $arr['running']) {
     $obj->setProperty('running', $arr['running']);
     //$obj->callMethod('');
    }

    if ($obj->getProperty('disabled') != $arr['disabled']) {
     $obj->setProperty('disabled', $arr['disabled']);
     //$obj->callMethod('');
    }
Сейчас из скрипта getWiFiclients есть вызовы методов Found и Lost класса WiFiCaps. А при событиях inactive, running и disabled данные только пишутся в свойства объекта класса WiFiCaps. Методы никакие не вызываются. Код //$obj->callMethod(''); оставил на будущее. А вдруг... Если нужно, можно создать эти методы в классе и вызывать их из скрипта. Но мне пока что нужны только свойства. Они используются в домашней странице. В таблице каждой точки можно увидеть её статус. И главное, есть ли у неё клиенты. Мне это очень помогало при настройке частот.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik

Сообщение Bagir »

Обновил свою презентацию, так сказать. Осталось только немного больше рассказать про рекурсивные маршруты в Микротик. Кто в курсе этой темы, разберутся со скриптом легко и сами. Но если ранее ни разу не сталкивались, то советую почитать в Интернете. После потраченного вечера и горы материала мозаика в голове сложится, и всё станет понятно.
Ещё хочу упомянуть момент работы с двумя провайдерами. Если мы выбираем рекурсивную маршрутизацию для определения Интернета за провайдером, то в микротике в таблице маршрутов, должны указать ip адрес, а не имя интерфейса. С именем не прокатит. Далее материал коснется тех, у кого для связи с провайдером поднимается PPPOE. В этом случае, IP адрес у вас может быть разный после реконекта. PPPOE это можно сказать туннель точка-точка. И в этом случае ваш ip адрес может быть любой. В большинстве случаев, провайдеру пофиг на это, и вы можете назначить адрес сами. Подглядите начало, и укажите похожий свой. Мой провайдер это съедает. И в итоге я имею постоянный ip для своего pppoe. Этот ip могу использовать в роутах, указывая его в рекурсивных маршрутах.
И вот парочка вопросов от меня:
1. Игрался ли кто с весьма новой возможностью Detect Internet? Это работает. Долбится с указанных интерфейсов к микротиковскому облаку. Где найдет, там и интернет. Мы могли бы это использовать. Я жутко хочу уйти от рекурсивных маршрутов, но пока что не вариант.
2. Мы можем читать таблицы микротика. А можем ли вносить изменения? Знаю что можем, но у меня нет рабочего примера. Я бы хотел при клике по виджету, менять дистанцию маршрутов разных провайдеров. Например, сейчас у меня основной для домашних устройств Билайн, а резервный Ростелеком. Жмак по виждету, и всё наоборот. Для этого мне надо поменять дистанцию у маршрута в таблице routes.

P.S. Добавил материал по поводу где ещё можно использовать класс wifi устройств.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik

Сообщение Bagir »

Уведомление об изменении состояния провайдеров. Код в большом сообщении обновлен.
Я не планировал объект или тем более класс для провайдеров. По сути, я не знаю какие действия в системе можно предпринять по поводу изменения их статуса. Но вот сообщить об этом не помешает.
Найдите код в сценарии getWiFiclients

Код: Выделить всё

  sg('isp1',$isp1);
  sg('isp2',$isp2);
и замените его на

Код: Выделить всё

 $pisp=gg('isp1');
 $isp=$isp1;
 $t='';
 if ($pisp<>$isp) {
  $p='Ростелеком';
  if ($isp==0) {$t="Потеря соединения c провайдером $p";}
  elseif ($isp==1 && $pisp==0) {$t="Установлено соединения c провайдером $p";}
  elseif ($isp==1 && $pisp>=2) {$t="Провайдером $p не предоставляет Интернет";}
  elseif ($isp==2 && $pisp<=1) {$t="Провайдером $p, Интернет предоставлен";}
  elseif ($isp==3) {$t="Провайдер $p выбран основным";}
  sg('isp1',$isp1);
  if ($t) { say($t); }
 }

 $pisp=gg('isp2');
 $isp=$isp2;
 $t='';
 if ($pisp<>$isp) {
  $p='Бинайн';
  if ($isp==0) {$t="Потеря соединения c провайдером $p";}
  elseif ($isp==1 && $pisp==0) {$t="Установлено соединения c провайдером $p";}
  elseif ($isp==1 && $pisp>=2) {$t="Провайдером $p не предоставляет Интернет";}
  elseif ($isp==2 && $pisp<=1) {$t="Провайдером $p, Интернет предоставлен";}
  elseif ($isp==3) {$t="Провайдер $p выбран основным";}
  sg('isp2',$isp2);
  if ($t) { say($t); }
 }
Теперь при смене состояния провайдеров вы будете получать сообщение.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik

Сообщение Bagir »

Есть всё же у меня задумка, как использовать фитчу микротика Detect Internet. Не знаю, можно ли с помощью этого уйти от рекурсивных маршрутов в роутах, но наличие Интернета на интерфейсе узнать точно можно. Включаем эту опцию в Микротике. У меня сделано так: Все интерфейсы провайдеров собраны в wan листе Detect Internet смотрит на wan лист интерфейсов. Пишем скрипт:

Код: Выделить всё

$ip = gg('Mikrotik_IP');
$login = gg('Mikrotik_login');
$password = gg('Mikrotik_password');

$API = new routerosAPI();
if ($API->connect($ip, $login, $password)) {
  $ARRAY = $API->comm('/interface/detect-internet/state/print');
  echo json_encode($ARRAY);

  $API->disconnect();
  echo 'ok'; 
} else { echo 'error'; }
получаем ответ:
[{
".id":"*1",
"name":"sfp1-gateway",
"state":"no-link",
"state-change-time":"jun\/10\/2020 12:50:50"
},{
".id":"*A",
"name":"ether9",
"state":"internet",
"state-change-time":"jun\/16\/2020 01:44:17",
"cloud-rtt":"112ms"
},{
".id":"*E",
"name":"pppoe-out1",
"state":"internet",
"state-change-time":"jun\/15\/2020 17:00:16",
"cloud-rtt":"59ms"
}]
Казалось бы всё просто круто. Парсим его и делов то. Но почему я не могу найти в Инете похожие примеры? Неужели есть подводные камни, или технология Detect Internet просто весьма новая.

P.S. Добавил этот способ в getWiFiclients вместо дополнительных рекурсивных маршрутов. Пока всё отлично, на тест, если всё хорошо, вечером выложу.

P.P.S. Вместо IP адресов и IDмаршрутов, можно в микротике добавить комментарий, а в getWiFiclients вылавливать запись по нему. Тоже вариант. Тут уж кому что понравится.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Maxtor
Сообщения: 13
Зарегистрирован: Сб мар 31, 2018 3:02 pm

Re: Mikrotik

Сообщение Maxtor »

Я не очень силен в кодах, есть одна программка MikroBIILL называется. Вот она может вертеть микротиком как хочет ! Для биллинга ее написали. Использую ее на работе для контроля юзеров. Может там подсмотреть коды ? http://www.mikro-bill.ru . Дома использую переключение провайдеров по методу вот www.technotrade.com.ua/Articles/mikroti ... -06-19.php чуть под себя поправил .
Вообще спасибо что в кодах Вы так все подробно описали куда что и как! Потихоньку вникаю и пробую свой идей! А вот насчет чтоб микрот отправлял значение в МД тоже актуально! Есть удаленные микротики, там бы им скрипт прописать и было-бы классно.
Maxtor
Сообщения: 13
Зарегистрирован: Сб мар 31, 2018 3:02 pm

Re: Mikrotik CAPs 2 провайдера Виджет Таблица устройств

Сообщение Maxtor »

Добавьте в метод activate объекта GuestsMode класс OperationalModes код

Код: Выделить всё

// перебор объектов класса
$objects=getObjectsByClass("WiFiDevice");
//перебрать объекты класса и собрать массив с именами друзей
foreach($objects as $obj) {
 $obj=getObject($obj['TITLE']);
 // Если online и друг
 if ($obj->getProperty('online')) {
  if (stripos($obj->getProperty('marker'), 'f')!==false) {
   $s=$obj->getProperty('owner');
   if ($s) {
    // взять до пробела (отбросить фамилию)
    $arr[]=explode(' ', $s)[0];
   } else {
    $arr[]='Неизвестный';
   }
 }}
}


$s='У нас гости.';

if (isset($arr)) {
 //Первый элемент массива
 $s.=' '.$arr[0];
 //со второго по предпоследний через запятую 
 for($i = 1, $size = count($arr)-1; $i < $size; ++$i) {
  $s.=', '.$arr[$i];
 }
 // последний через "и"
 if (count($arr) > 1) {
  $s.=' и '.end($arr);
 } 
 // вывод
 //echo $s;
 say($s, (gg('GuardMode.status')>1)?3:2);
}
И получите уведомление кто к вам пришел при активации режима "У нас гости". По аналогии можно добавить любые свои флаги.


Создайте сценарий friendshere

Код: Выделить всё

 // Получить все объекты класса
 $objects = getObjectsByClass('WiFiDevice'); 

 // перебор объектов класса WiFiDevice
 // Поиск первого совпадения. Устройство друга в сети
 foreach ($objects as $obj) {
  $obj=getObject($obj['TITLE']);

  if ($obj->getProperty('online')) {
   if (stripos($obj->getProperty('marker'), 'f') !== false) {
    $f = true;
    break;
   }
  }
 }

 // Решение о изменении состояния режима
 if (gg('GuestsMode.status')) {
  if (!$f) { cm('GuestsMode.deactivate'); }
 } else {
  if ($f) { cm('GuestsMode.activate'); }
 }
И запускайте его, например из методов Found и Lost телефонов своих друзей. Вы получите активацию и деактивацию режима "У нас гости". Лично я пока что не знаю как по другому определять этот режим, кроме как по мобильным телефонам.
[/quote]
А деактивировать те же скриптом ?
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Mikrotik CAPs 2 провайдера Виджет Таблица устройств

Сообщение Bagir »

Maxtor писал(а): Вт июн 16, 2020 2:56 pmА деактивировать те же скриптом ?
Да, Скрипт friendshere активирует и деактивирует режим GuestsMode. Там в самом конце это действие. Скрипт перебирает массив класса, и если не нашел гостей (флаг f) то активирует, иначе деактивирует. Скрипт запускаем из методов Found и Lost устройств гостей. Сделал так, чтобы при каждом WiFi устройстве скрипт попусту не перебирал объекты класса.
Код в методе activate объекта GuestsMode класс OperationalModes только готовит список гостей, и дает уведомление say()
Maxtor писал(а): Вт июн 16, 2020 2:10 pmДома использую переключение провайдеров по методу вот www.technotrade.com.ua/Articles/mikroti ... -06-19.php
Netwatch для переключения провайдеров. У мена раньше так было. Потом ушел на рекурсивные маршруты. Там только в роутах всё прописывается, не сложно когда разобрался.
Я сейчас мониторю Интернет за провайдером по выше упомянутому Internet Detect. Код с утра написал. пока всё норм. Так что теперь не важно для сценария, рекурсия там или Netwatch. Сегодня выложу вечером.
Maxtor писал(а): Вт июн 16, 2020 2:10 pmнасчет чтоб микрот отправлял значение в МД тоже актуально! Есть удаленные микротики
Можно объединить методы работы с микротами. Скрипт getWiFiclients пишет свойства в объекты классов и вызывает их методы. Можно параллельно сделать второй способ, когда микрот сам шлет сообщения, и рулить этими же классами устройств. Будет общий универсальный вариант.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Ответить