Моя сеть
Несколько микротиков в режиме Caps-Man. Все обращения будут к главному.
Если у вас только один микротик и Caps-Man не используется, то в сценарии можно указать другую таблицу с WiFi устройствами роутера, закомментировать блок кода получения CAPs точек, и не добавлять класс WiFiCaps
2 провайдера Ростелеком и Билайн. Оба провайдера активные. Основной BL, если недоступен, то Интернет будет через РТ.
Если у вас только один провайдер, закомментируйте блок кода в сценарии. Связи с классами по этому моменту никакой нет.
Классы
Во вложении классы WiFiDevice и WiFiCaps. Код в общих методах классов только сообщает о приходе и уходе устройств из сети. Конкретные действия прописываются в личном коде устройства. Пример будет ниже.
Сценарий опроса Микротика
getWiFiclients это главный сценарий который периодически опрашивает Микротик, записывает данные в объекты классов WiFiDevice и WiFiCaps, и вызывает их методы. getWiFiclients вызывает сам себя каждые 10 секунд по средствам функции setTimeOut. Но его нужно запустить, и поддерживать в работе. Добавьте в метод onNewMinute класса Timer код
Код: Выделить всё
setTimeOut('getWiFiclientsTimer',"runScript('getWiFiclients');",10);
Код: Выделить всё
$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 работает как функция. Мы ей имя точки как в микротике, а она нам массив дружественных имен из двух падежей.
Код: Выделить всё
/* Возвращает дружественное имя точек доступа 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;
Домашняя страница с таблицей устройств
Нам будет нужно посмотреть, какие устройства сейчас в сети, и какие были совсем недавно. Для этого создадим домашнюю страницу с типом Ссылка, которая будет запускать скрипт для составления таблицы.
В настройках страницы:
Ссылка: http://localhost/objects/?script=wifiTable&print=1
исправьте адрес сервера на свой
Код: Выделить всё
$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='•';} else {$t=' ';} echo '<td align="center" style="color:#008000"><big>'.$t.'</big></td>';
if ($obj->getProperty('inactive') == 'true' ) {$t='•';} else {$t=' ';} echo '<td align="center" style="color:#ff0000"><big>'.$t.'</big></td>';
if ($obj->getProperty('running') == 'true' ) {$t='•';} else {$t=' ';} echo '<td align="center" style="color:#000080"><big>'.$t.'</big></td>';
if ($obj->getProperty('disabled') == 'true' ) {$t='•';} else {$t=' ';} echo '<td align="center" style="color:#ff0000"><big>'.$t.'</big></td>';
echo '</tr>';
}
// Закрываем таблицу
if ( $f) { echo '</table></blockquote></details>'; }
$f=0;
Красивый элемент на сцене
Код: Выделить всё
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%);
}
Код: Выделить всё
<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>
Цвет провайдеров будет меняться в зависимости от значений свойств isp1 и isp2.
На линиях будут крестики при неактивном провайдере и отсутствии Интернета за ним.
К примеру у меня сейчас активны оба провайдера, у обоих есть Интернет, и второй выбран основным.
При нажатии на провайдеров вызывается скрипт runScript("isp1select"); и runScript("isp2select");
Скрипт меняет дистанцию провайдера. Так можно быстро выбрать основным провайдером другого, если на то есть необходимость.
У меня у isp2 дистанция всегда 20. У isp2 cкриптами isp1select меняю на 10, isp2select на 30, тем самым маршрут isp1 встает до или после isp2
Код: Выделить всё
$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'; }
Пример настройки методов объекта телефона
Код: Выделить всё
switch ($this->getProperty('CAPname')) {
case 'CAP--BagirS-1':
say('Открываю Серёже входную дверь');
callMethod(.....................);
break;
}
телефон может сесть на это точку когда уже буду дома.
Код: Выделить всё
switch ($this->getProperty('CAPname')) {
case 'CAP--Bagir-1':
// Включить прожекторы у подъезда, если телефон обнаружен на этой точке
cm('DrivewayArea.onActivity');
break;
case 'CAP--BagirS-1':
// Открыть дверь
say('Открываю Серёже входную дверь');
callMethod('..............');
break;
}
Код: Выделить всё
switch ($this->getProperty('CAPname')) {
case 'CAP--SXT-1':
cm('Gazebo.onActivity');
break;
case 'CAP--hAPmini-1':
cm('KitchenArea.onActivity');
break;
}
Код: Выделить всё
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'); }
}