Mikrotik

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

Модератор: immortal

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

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

Сообщение Bagir » Пн июн 15, 2020 12:01 pm

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


Моя сеть
Несколько микротиков в режиме 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 для опроса микротикаПоказать

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

$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 работает как функция. Мы ей имя точки как в микротике, а она нам массив дружественных имен из двух падежей.
CAPsFriendlyNameПоказать

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

/* Возвращает дружественное имя точек доступа 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 КБ) 3327 просмотров
Для этого создадим домашнюю страницу с типом Ссылка, которая будет запускать скрипт для составления таблицы.
В настройках страницы:
Ссылка: http://localhost/objects/?script=wifiTable&print=1
исправьте адрес сервера на свой
Сценарий wifiTableПоказать

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

$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 КБ) 3156 просмотров
Дополнительный код CSSПоказать

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

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 код элементаПоказать

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

<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
скрипт isp1selectПоказать

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

$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 КБ) 3316 просмотров
МетодыПоказать
Метод 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 КБ) 139 скачиваний
WiFiCaps.txt
(2.92 КБ) 147 скачиваний
WiFiDevice.txt
(8.76 КБ) 145 скачиваний
Последний раз редактировалось Bagir Вт июн 23, 2020 12:00 am, всего редактировалось 17 раз.
За это сообщение автора Bagir поблагодарили (всего 5):
Plug (Пн июн 15, 2020 1:14 pm) • Maxtor (Пн июн 15, 2020 1:18 pm) • Chainik (Пн июн 15, 2020 2:28 pm) • Amarok (Пт июн 19, 2020 5:50 am) • d.dm.sp (Вс июн 28, 2020 7:30 am)
Рейтинг: 5.81%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Maxtor
Сообщения: 13
Зарегистрирован: Сб мар 31, 2018 3:02 pm
Благодарил (а): 10 раз
Поблагодарили: 1 раз

Re: Mikrotik

Сообщение Maxtor » Пн июн 15, 2020 4:57 pm

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

Re: Mikrotik

Сообщение Bagir » Пн июн 15, 2020 9:46 pm

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 pm
CAPsFriendlyName и 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
все заработало
Круто! Даже не думал, что так всё хорошо подойдет. Очень рад.
За это сообщение автора Bagir поблагодарил:
Maxtor (Пн июн 15, 2020 10:02 pm)
Рейтинг: 1.16%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Пн июн 15, 2020 10:15 pm

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(''); оставил на будущее. А вдруг... Если нужно, можно создать эти методы в классе и вызывать их из скрипта. Но мне пока что нужны только свойства. Они используются в домашней странице. В таблице каждой точки можно увидеть её статус. И главное, есть ли у неё клиенты. Мне это очень помогало при настройке частот.
За это сообщение автора Bagir поблагодарил:
Maxtor (Пн июн 15, 2020 10:17 pm)
Рейтинг: 1.16%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Вт июн 16, 2020 1:10 am

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

P.S. Добавил материал по поводу где ещё можно использовать класс wifi устройств.
За это сообщение автора Bagir поблагодарил:
Maxtor (Вт июн 16, 2020 2:21 pm)
Рейтинг: 1.16%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Вт июн 16, 2020 9:44 am

Уведомление об изменении состояния провайдеров. Код в большом сообщении обновлен.
Я не планировал объект или тем более класс для провайдеров. По сути, я не знаю какие действия в системе можно предпринять по поводу изменения их статуса. Но вот сообщить об этом не помешает.
Найдите код в сценарии 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
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Вт июн 16, 2020 12:16 pm

Есть всё же у меня задумка, как использовать фитчу микротика 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
Благодарил (а): 10 раз
Поблагодарили: 1 раз

Re: Mikrotik

Сообщение Maxtor » Вт июн 16, 2020 2:10 pm

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

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

Сообщение Maxtor » Вт июн 16, 2020 2:56 pm

Добавьте в метод 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
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

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

Сообщение Bagir » Вт июн 16, 2020 5:43 pm

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
Ответить