Mikrotik

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

Модератор: immortal

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

Re: Mikrotik

Сообщение Bagir » Чт июн 18, 2020 10:00 pm

xor писал(а):
Ср июн 17, 2020 9:31 pm
а он заведен у вас как устройство онлайн? такие устройства пингуются системой и можно поймать его отвал, в т.ч., и по питанию
Нет, скрипт просто лазает в микротик каждые 10 секунд. Действительно мудрая мысль. Завести микрот в устройства онлайн, и в скрипт добавить проверку. Если не решусь писать цикл, то так и сделаю. Это должно уберечь от подвисания системы в таких, пускай даже крайне редких случаях.
Amarok писал(а):
Чт июн 18, 2020 7:11 am
Фоточки будут?
Конечно, всё есть в презентации viewtopic.php?f=8&t=2006&sid=8c96836c6f ... 20#p120957
Тема не в начале ветки, но этот пост буду и дальше дополнять. Так что кому интересно, ссыль в закладки.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Чт июн 18, 2020 11:31 pm

Мысли по поводу цикла для микротика:
1. Убиваем момент при неудачных соединениях. Время следующей попытки будет удваиваться, но не реже чем один час. Это не нагрузит систему, да ещё при условии, что всё происходит в отдельном процессе.
2. Соединение не будет завершаться каждое выполнение сценария.
образец циклаПоказать

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

<?php

chdir(dirname(__FILE__) . '/../');

include_once("./config.php");
include_once("./lib/loader.php");
include_once("./lib/threads.php");

set_time_limit(0);

include_once("./load_settings.php");
include_once(DIR_MODULES . "control_modules/control_modules.class.php");

$ctl = new control_modules();
$checked_time = 0;

echo date("H:i:s") . " running " . basename(__FILE__) . PHP_EOL;

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

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

$sleepErrorTime=60; 

while (1) {
   // штатно
   if ((time()-$checked_time)>10) {
      $checked_time = time();
      setGlobal((str_replace('.php', '', basename(__FILE__))) . 'Run', time(), 1);
   }

   // устанавливаем соединение с микротиком, если оно не создано
   if ($API->connected==0) { 
     if ($API->connect($ip, $login, $password)) { 
       echo 'connect successfully';
       // сброс времени задержки при неудачном соединении 
       $sleepErrorTime=60; 
     } else { 
       echo 'error connected';
       sleep($sleeptime);
       // увеличиваем время следующей попытки соединения вдвое, но не более одного часа
       $sleepErrorTime=min($sleepErrorTime*2, 1*60*60);
       // перейти к следующей итерации
       continue;
     }
   }


   // код тела сценария getWiFiclients



   // штатно
   if (file_exists('./reboot') || IsSet($_GET['onetime'])) {
      // завершить соединение с микротиком
      $API->disconnect();
      exit;
   }
   sleep(10);
}

DebMes("Unexpected close of cycle: " . basename(__FILE__));
Что думайте на счет этого?

Есть правда один момент. Мне хотелось бы закрывать цикл правильно, не обухом по голове с помощью taskkill, а используя exit; и перед ним $API->disconnect();

P.S. Запустил на тест. Вроде всё хорошо. Завтра увидим. user Алиса зашла в микротик один раз и сидит там. Завтра сделаю стресс тестирование.
При аварийном закрытии цикла, пользователь сразу уходит. Так что хоть $API->disconnect(); и правильное решение, но можно из него.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
xor
Сообщения: 2038
Зарегистрирован: Сб ноя 22, 2014 8:45 pm
Благодарил (а): 284 раза
Поблагодарили: 629 раз

Re: Mikrotik

Сообщение xor » Пт июн 19, 2020 1:59 am

Bagir писал(а):
Чт июн 18, 2020 11:31 pm

Есть правда один момент. Мне хотелось бы закрывать цикл правильно, не обухом по голове с помощью taskkill, а используя exit; и перед ним $API->disconnect();
кладите файл mikrotik_stop по аналогии с reboot, при наличии файлика аккуратно выходите с дисконнектом и экзитом (ну и файлик подотрите перед выходом)
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Пт июн 19, 2020 12:18 pm

xor писал(а):
Пт июн 19, 2020 1:59 am
кладите файл mikrotik_stop по аналогии с reboot, при наличии файлика аккуратно выходите с дисконнектом и экзитом
Пробовал такой способ на цикле для самогонного аппарата. При этом сработает код

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

   if (file_exists('./reboot') || IsSet($_GET['onetime'])) {
      exit;
   }
Так же можно по своему условию тормознуть цикл командой exit; Но тут двое граблей. Во первых цикл сразу перезапустится алгоритмом авторекавери, а во вторых запишется ошибка об аварийном завершении цикла. Я ещё раз проверил, при завешрении процесса цикла, пользователь выходит из микротика. Так что оставляю как есть, не делая $API->disconnect(); По сути все остальные циклы так же поступают.
Вообщем пока что очень доволен вариантом с циклом. Обращения к микротику у меня каждые 10 секунд.
Похоже понравились мне циклы, переделываю на них всё, что часто запускается, чтобы уйти от рекурсии с таймерами.
Пробовал ситуацию с отказом микротика. Тормозов больше никаких нет. Ещё потестирую и выложу что получилось.
За это сообщение автора Bagir поблагодарил:
Chainik (Пт июн 19, 2020 12:26 pm)
Рейтинг: 1.16%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Chainik
Сообщения: 1462
Зарегистрирован: Вс янв 10, 2016 11:05 am
Благодарил (а): 260 раз
Поблагодарили: 454 раза

Re: Mikrotik

Сообщение Chainik » Пт июн 19, 2020 12:43 pm

Bagir, спасибо что делитесь наработками с сообществом. Было бы классно, если бы вы выложили простую "общую" инструкцию по поводу циклов. Не сомневаюсь, что ваш код работает, но там присутствует множество завязок на специфические объекты (будь-то связанные с роутером или с самогонным аппаратом).

А я имею ввиду общую ситуацию. Допустим, надо опрашивать какой-то датчик. Ну, к примеру

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

$value = file_get_contents("http://192.168.0.14/sec/?pt=31&cmd=get");
// и т.д.
Что нужно сделать (что, куда прописать), чтобы организовать цикл для частого опроса? Как лучше проверять условие завершения цикла изнутри? Как при необходимости корректно завершить выполнение цикла ("снаружи")? Есть ли способ понять, "вертится" ли цикл или "упал", не анализируя результаты того, что должен был делать цикл (чтобы, если вдруг цикл "упал", перезапустить его). И тому подобные значимые вопросы.

Короче говоря, очень не хватает краткой "общей" инструкции с минимально необходимым количеством кода. Было бы здорово составить краткую пошаговую инструкцию. Не сомневаюсь, сообщество оценит ваши усилия и ликбез по этому поводу.

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

Re: Mikrotik

Сообщение Bagir » Пт июн 19, 2020 1:05 pm

Chainik писал(а):
Пт июн 19, 2020 12:43 pm
Все это не срочно, а когда у вас появится "окошко" между делами
Конечно следаю. Этот форум уже давно стал наполовину моей записной книжкой. Я часто читаю свои темы )) которые выкладывал давно. Ответы у меня есть на все вопросы, просто сейчас пора бежать. В выходные подготовлю материал. Есть правда ещё не до конца решенный жирный такой вопрос в этой теме по поводу авторекавери. Но со временем мы во всём разберемся. Циклы очень полезная штука. Сильно разгружают систему.
За это сообщение автора Bagir поблагодарили (всего 2):
Chainik (Пт июн 19, 2020 2:28 pm) • Maxtor (Пт июн 19, 2020 3:19 pm)
Рейтинг: 2.33%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Chainik
Сообщения: 1462
Зарегистрирован: Вс янв 10, 2016 11:05 am
Благодарил (а): 260 раз
Поблагодарили: 454 раза

Re: Mikrotik

Сообщение Chainik » Пт июн 19, 2020 2:32 pm

Bagir писал(а):
Пт июн 19, 2020 1:05 pm
...Этот форум уже давно стал наполовину моей записной книжкой. Я часто читаю свои темы )) которые выкладывал давно. ...
Сам так же делаю... )))
Иногда проще "скопипастить" проверенный код, чем писать все с нуля, с вероятностью где-нибудь накосячить, а потом долго искать. Ну и нет необходимости держать в голове все особенности синтаксиса.
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Вт июн 23, 2020 12:01 am

Обновил топик с презентацией viewtopic.php?f=8&t=2006&p=120957#p120957

Альтернативный вариант с использованием цикла
Во вложении есть файл cycle_microtik. Распакуйте его и положите в папку scripts где лежат все файлы циклов. При этом уберите все точки запуска сценария getWiFiclients, например в метод onNewMinute класса Timer. Сам сценарий getWiFiclients тоже при этом не нужен. Весь его код находится в файле cycle_microtik. Исправьте id и имена интерфейсов на свои. Запустите цикл cycle_microtik из X-Ray -> Services, или перезапустите все циклы.
В данном случае плюсы цикла перед сценарием:
- логинимся в микротике только один раз, а не каждый запуск сценария;
- код выполняется в отдельном процессе и не мешает системе;
- при неудачном обращении к микротику, следующая попытка идет с задержкой.
- время чтения можно увеличить. Мне хватает каждые 10 секунд, но легко можно и чаще;
- не используем таймеры для частого запуска сценария;
- меньше действий в системе, и меньше кода в разных модулях.
За это сообщение автора Bagir поблагодарили (всего 2):
Chainik (Вт июн 23, 2020 8:36 am) • Maxtor (Ср июн 24, 2020 3:14 pm)
Рейтинг: 2.33%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1613
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 374 раза

Re: Mikrotik

Сообщение Bagir » Сб июн 27, 2020 11:47 pm

Чего то приуныла тема, поднимем? С двумя провайдерами бывает ситуация, когда основной недоступен, и при этом используется резервный, т.е. следующий по дистанции. На виджете видно, какой провайдер используется в данный момент, но не видно какой выбран основным. Вот рабочий вариант:
Интернет 2.png
Интернет 2.png (15.94 КБ) 3365 просмотров
Стрелочка показывает какой провайдер ближе по дистанции. И если возникнет ситуация, когда основной провайдер будет неактивен, то резервный станет синим цветом, а стрелочка будет продолжать указывать на другого. Кликом по иконке провайдера мы можем выбрать другого. Скрипт выбора я выкладывал ранее. А вот и код для чтения дистанции провайдеров:

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

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

  // Дистанция провайдера
  if ($isp1dst<$isp2dst) {
   sg('ispmain',1);
  } else {
   sg('ispmain',2);
  }
Его можно вставить с скрипт или цикл. При этом будет записано свойство ispmain в котором будет 1 или 2. Это свойство читается в виджете. Код для него:

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

 <!-- Флаги -->
 <defs>
  <g id="flag8549">
  <path d="M5 0 L0 9 L10 9 Z" />
  </g>
 </defs>
 
 <g transform="translate(10, 80)" >
  <use href="#flag8549" style='display:%ThisComputer.ispmain|"none;block;none"%'/>
 </g>
 <g transform="translate(90, 80)" >
  <use href="#flag8549" style='display:%ThisComputer.ispmain|"none;none;block"%'/>
 </g>
Вариант рабочий, просто треугольник. Потом заменю на флажок наверное.
Осталось только анимировать нажатия по иконкам провайдеров, чтобы был виден клик по нему. Например вспышка фоновой подсветки. Тут на помощь скорее всего придет CSS. Киньте простенький примерчик, добавлю.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Chainik
Сообщения: 1462
Зарегистрирован: Вс янв 10, 2016 11:05 am
Благодарил (а): 260 раз
Поблагодарили: 454 раза

Re: Mikrotik

Сообщение Chainik » Вс июн 28, 2020 9:00 am

Bagir писал(а):
Сб июн 27, 2020 11:47 pm
...
Осталось только анимировать нажатия по иконкам провайдеров, чтобы был виден клик по нему. Например вспышка фоновой подсветки. Тут на помощь скорее всего придет CSS. Киньте простенький примерчик, добавлю.
Пусть не вспышка фоновой подсветки, а имитация нажатия путем кратковременного уменьшения размера, но для HTML-блока такой пример у меня успешно работал.

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

<style type="text/css">
.gorizontalno {
display: inline-block
}

.button:active {
  transform: scale(0.9, 0.9);
}
</style>
Код вставлял непосредственно в тело HTML.
За это сообщение автора Chainik поблагодарил:
Bagir (Вс июн 28, 2020 11:50 am)
Рейтинг: 1.16%
Ответить