-
Similar Content
-
By Kitsum
Просмотреть файл [esp8266] Библиотека CMD, реализует настройку микроконтроллера и управление вашей программой через терминал.
Основная задача библиотеки, это прием пользовательских команд через UART интерфейс, их обработка и выполнение пользовательского кода, связанного с той или иной командой.
Данная библиотека позволяет реализовать:
Управление микроконтроллером Любую настройку, будь то WiFi, другие библиотеки или часть Вашей программы Вызывать Ваши задачи (функции) из терминала по команде и передавать им требуемые параметры Использовать контроллер в качестве шлюза между датчиками и программами на PC Внимание: любая команда, передаваемая в терминал обязана заканчиваться символом перевода строки "\n".
Подключение библиотеки
#include <cmd.h> Инициализация объекта, к которому мы будем обращаться для добавления команд. В качестве параметра объекту необходимо передать указатель на объект Serial или любой другой схожий по типу интерфейс.
cmd command(&Serial); В функции Setup описываем какие команды требуется обрабатывать. Например, по команде "test" вызывать пользовательскую функцию с именем "myFunctionName". Имя пользовательской функции может быть абсолютно любым.
void Setup() { Serial.begin(115200); command.add("test", myFunctionName); } Пользовательская функция будет вызываться каждый раз, когда по интерфейсу Serial поступит команда "test". Если команда будет передана с параметрами, то эти параметры будут переданы в качестве аргументов пользовательской функции.
В функции loop должна находится команда вызова обработчика.
void loop() { command.handleEvents(); } Пользовательская функция обязана соответствовать ряду требований:
Не возвращать никакого результата (быть объявленной с типом void) Принимать в качестве первого аргумента переменную с типом byte в которой будет храниться число равное количеству переданных параметров Принимать в качестве второго параметра переменную с типом char** в которой будет храниться указатель на массив со всеми указателями (char*) на переданные параметры void myFunctionName(byte argc, char** argv) { /* ... */ } Функция всегда должна иметь такой вид, даже если не подразумевается, что ей будут передаваться какие-либо параметры.
Чтобы перебрать все переданные параметры и вывести их в консоль, можно воспользоваться следующим примером
void myFunctionName(byte argc, char** argv) { if (0 < argc) { for (uint8_t i = 0; i < argc; i++) { Serial.printf("%i. %s\n", i, argv[i]); } } } Пример вызова пользовательской функции без параметров и с ними
# test No parameter was passed # test p1 p2 p3 p4 p5 0. p1 1. p2 2. p3 3. p4 4. p5 Помните, что параметры представлены в виде указателей и работать с ними нужно как с обычными переменными не получится т.к указатель содержит не значение переменной (переданный параметр), а указатель на ту область памяти микроконтроллера в которой это значение находится.
Чтобы сравнить два значения, например, параметр под индексом 0 (идет первым в списке) с каким-либо значением в программе, воспользуйтесь функцией strcmp, которая возвращает целочисленное значение, указывающее на лексическое расхождение строк. Если строки равны, то возвращаемое значение равно 0.
if (!strcmp(argv[0], "wifi")) { Serial.println(F("Первый аргумент WiFi")); } else { Serial.println(F("Первый аргумент НЕ WiFi!!!")); } Для копирования значения указателя в другую переменную с типом char можно воспользоваться функцией strcpy
char myVar[20]; strcpy(myVar, argv[0]); if (myVar == "123456") { Serial.prinln(F("ok")); } Также можно обернуть указатель объектом String и получить весь функционал этого объекта, который будет содержать значение параметра
String param1(argv[0]); // String param1 = argv[0]; Serial.printf("argv[0] length: %i\n", param1.length()); Serial.printf("argv[0] is integer?: %s\n", param1.toInt() ? "YES" : "NO"); if (param1 == "qwerty") { Serial.println(F("Hello QWERTY!")); } С библиотекой идут несколько примеров, в том числе и пример конфигурации WiFi в режиме STA.
Автор Kitsum Добавлен 05.12.2018 Категория Библиотеки
-
By Kitsum
Основная задача библиотеки, это прием пользовательских команд через UART интерфейс, их обработка и выполнение пользовательского кода, связанного с той или иной командой.
Данная библиотека позволяет реализовать:
Управление микроконтроллером Любую настройку, будь то WiFi, другие библиотеки или часть Вашей программы Вызывать Ваши задачи (функции) из терминала по команде и передавать им требуемые параметры Использовать контроллер в качестве шлюза между датчиками и программами на PC Внимание: любая команда, передаваемая в терминал обязана заканчиваться символом перевода строки "\n".
Подключение библиотеки
#include <cmd.h> Инициализация объекта, к которому мы будем обращаться для добавления команд. В качестве параметра объекту необходимо передать указатель на объект Serial или любой другой схожий по типу интерфейс.
cmd command(&Serial); В функции Setup описываем какие команды требуется обрабатывать. Например, по команде "test" вызывать пользовательскую функцию с именем "myFunctionName". Имя пользовательской функции может быть абсолютно любым.
void Setup() { Serial.begin(115200); command.add("test", myFunctionName); } Пользовательская функция будет вызываться каждый раз, когда по интерфейсу Serial поступит команда "test". Если команда будет передана с параметрами, то эти параметры будут переданы в качестве аргументов пользовательской функции.
В функции loop должна находится команда вызова обработчика.
void loop() { command.handleEvents(); } Пользовательская функция обязана соответствовать ряду требований:
Не возвращать никакого результата (быть объявленной с типом void) Принимать в качестве первого аргумента переменную с типом byte в которой будет храниться число равное количеству переданных параметров Принимать в качестве второго параметра переменную с типом char** в которой будет храниться указатель на массив со всеми указателями (char*) на переданные параметры void myFunctionName(byte argc, char** argv) { /* ... */ } Функция всегда должна иметь такой вид, даже если не подразумевается, что ей будут передаваться какие-либо параметры.
Чтобы перебрать все переданные параметры и вывести их в консоль, можно воспользоваться следующим примером
void myFunctionName(byte argc, char** argv) { if (0 < argc) { for (uint8_t i = 0; i < argc; i++) { Serial.printf("%i. %s\n", i, argv[i]); } } } Пример вызова пользовательской функции без параметров и с ними
# test No parameter was passed # test p1 p2 p3 p4 p5 0. p1 1. p2 2. p3 3. p4 4. p5 Помните, что параметры представлены в виде указателей и работать с ними нужно как с обычными переменными не получится т.к указатель содержит не значение переменной (переданный параметр), а указатель на ту область памяти микроконтроллера в которой это значение находится.
Чтобы сравнить два значения, например, параметр под индексом 0 (идет первым в списке) с каким-либо значением в программе, воспользуйтесь функцией strcmp, которая возвращает целочисленное значение, указывающее на лексическое расхождение строк. Если строки равны, то возвращаемое значение равно 0.
if (!strcmp(argv[0], "wifi")) { Serial.println(F("Первый аргумент WiFi")); } else { Serial.println(F("Первый аргумент НЕ WiFi!!!")); } Для копирования значения указателя в другую переменную с типом char можно воспользоваться функцией strcpy
char myVar[20]; strcpy(myVar, argv[0]); if (myVar == "123456") { Serial.prinln(F("ok")); } Также можно обернуть указатель объектом String и получить весь функционал этого объекта, который будет содержать значение параметра
String param1(argv[0]); // String param1 = argv[0]; Serial.printf("argv[0] length: %i\n", param1.length()); Serial.printf("argv[0] is integer?: %s\n", param1.toInt() ? "YES" : "NO"); if (param1 == "qwerty") { Serial.println(F("Hello QWERTY!")); } С библиотекой идут несколько примеров, в том числе и пример конфигурации WiFi в режиме STA.
-
By Kitsum
Описанный ниже велосипед является продолжением одной из моих статей на другом, интересном мне, ресурсе. Продолжение и все последующие обновления будут происходить только на it4it.club
Для начала, хочу процитировать самого себя и тем самым дать пояснения: почему, зачем и для кого это нужно.
Данная тема получила большую популярность у коллег и не раз выручила Вашего покорного слугу, не дав разгореться стулу на котором он сидит.
Но имеющегося функционала стало не хватать, требовалось не только слышать и иногда видеть, а еще получать удаленный доступ к оборудованию и лицезреть всю картину в целом.
Задача поставлена, идем исполнять, но с начало забегу немного вперед и продемонстрирую текущий функционал.
Общее окно программы переработано и теперь отображает список всех групп из Zabbix с их хостами. Список активных триггеров переехал в нижнюю часть окна и отображает дополнительную информацию об узлах с которыми не все гладко. Сам список можно увеличивать, если все совсем плохо, или уменьшать если выражение "Хьюстон у нас проблемы" Вы слышите только в фильмах. Также появились цветные маркеры важности триггера. По двойному клику по активному триггеру мы перемещаемся в соответствующую группу где находится проблемный узел.
Не забыли и про то, ради чего вся начальная песня и писалась - трей с всплывающими оповещениями и звуковым сигналом. Основное окно сворачивается именно туда, чтобы не залеживаться на панели где ценится каждый свободный пиксель.
Хосты в группах стали кликабельны, правда пока только ПКМ, и имеют всплывающее меню позволяющее выполнять банальные действия:
Подключение к узлу:
Telnet SSH RDP VNC Проверка соединения:
Ping Traceroute Естественно его можно расширить, добавив всяких вкусностей по мере возрастания аппетита IT отдела.
Программа по прежнему имеет серверную и клиентскую часть, что позволило организовать кэширование запросов и осуществлять оповещения в момент определения проблемы сервером, а не по таймеру обновления, как это организовано в dashboard zabbix. Раньше узнали о проблеме, раньше приступили к устранению. Естественно и устаревшие триггеры убираются также оперативно.
Также это позволило избавить программу от информации о доступе к серверу, что мне кажется не приемлемым для оповещалки. Чем меньше дырок, тем крепче сон.
Приступим к реализации.
Ну и естественно, Ваш покорный слуга еще не научился писать на C++ ничего более сложного чем "Hello World", поэтому клиент и сервер будет написан на PHP. За исключением того момента, что клиентская часть (при помощи магии Гарри Поттера) станет бинарным файлом. Бог с ним, серверная часть не доступна обывателю, а это самое важное!!!
Для начала, нужно придумать безопасный и понятный алгоритм не нагружающий сервер т.к клиентов может быть 100и или 1000и, всякое бывает. Все не безопасные команды обязаны выполняться на сервере без участия клиента. Дальнейшая работа клиента: обработка данных, выполнение действий с триггерами и т.п должно выполняться только у клиента, не затрагивая сервер.
При обращении клиента к серверу по http происходит проверка его ip на наличие в списках разрешенных. В противном случае показываем фигу. Проверяем, наличие актуального кеша, и отдаём его. Если кеша нет, генерируем новый. Если запрос прилетел от zabbix: принудительно считаем кеш устаревшим, генерируем новый и после этого рассылаем всем клиентам оповещения по UDP протоколу. Это позволит свести расход ресурсов базы данных к нулю т.к все клиенты ринутся забирать новые данные, а все уже в кеше. Супер, все дешево и сердито.
Серверная часть представляет из себя файл index.php где-то на Вашем web сервере. Актуально для Zabbix 2.4 (скорее всего будет актуальна и для последующих версий, будем проверять по мере возрастания аппетита).
Для дополнительной безопасности рекомендую создать отдельную учетную запись в базе данных с правами только на чтение и только к базе zabbix. Это актуально в наши дни.
Переходи в zabbix
Первым делом переходим в Настройка -> Действия -> Источники события: Триггеры и создать новое действие. Назовем случайным образом, например Report problems to ZabbixTrigger.
В условиях выставляем
Значение триггера = ПРОБЛЕМА Значение триггера = OK Это все необходимо, чтобы проблемы в GUI появлялись и исчезали точно именно тогда, когда это происходит в Zabbix (не путать с dashboard).
Вкладка "Операции" должна выглядеть следующим образом. Естественно что путь до php скрипта должен быть вашим.
Вуаля! Если Вы все сделали правильно (без кардинальных изменений), то я рад приветствовать нового ездока моего велосипеда. Поедем тандемом!
Сам клиент прикреплен в конце поста.
Для тех, кто читает титры в кинотеатре
При запуске будет создан файл config.ini в корне программы. При необходимости, измените его настройки, благо их не много.
[server] url="http://zabbix/zabbix-gui" update="60" [client] showalarm="20" Параметр url отвечает за http путь до скрипта на сервере, update за интервал (в секундах) обновления данных с сервера, а showalarm вроде как должен влиять на время отображения всплывающей подсказки в трее.
Теперь немного структуры.
В каталоге sounds находится звук оповещения о новом триггере, формат ogg Каталог icons содержит маркеры триггеров. trigger00 - для нормального состояния, а все последующие соответствуют начальным настройкам zabbix во вкладке Администрирование -> Общие раздел Важность триггеров. Можете изменить на свои цвета, программа все подхватит при перезагрузки. Ну и на закуску каталог ext, это как говорится для меломанов, содержит фри программы для обработки внешних действий клиента. Вы можете заменить их на свои при условии, что стандартные имена параметров запуска и их последовательность совпадают. PS: На этом все, спасибо тем кого это заинтересовало. Предлагайте свои идеи или способы доработки велосипеда. А если найдется программист на C++ так милости просим. В любом случае, функционал будет в дальнейшем расширяться.
zabbixTrigger.zip
-
By Kitsum
Всем доброе время суток.
Сегодня пойдет речь об одном из вариантов сбора информации о лицензиях операционных системах Windows и некоторого сопутствующего программного обеспечения. Для сбора будет использована утилита ProduKey, это далеко не идеальный вариант, но вполне приемлемый, если нет иных средств мониторинга, и требуется что-то быстро слепить на коленке без траты денег.
И так, имеется группа компьютеров находящихся в домене, подсеть 10.10.10.0/24, ProduKey запускается от учетной записи администратора домена или администратора той ветки, к которой принадлежит подсеть.
Программой можно пользоваться как в графическом интерфейсе, так и в консольном режиме. Последний вариант, лично для меня, более предпочтителен.
ВАЖНО: нам требуется программа только на Английском языке т.к имена ключей использующихся в отчетах должны соответствовать именам ключей в PHP скрипте далее.
В корне с программой создаем .bat файл со следующим содержимым
produkey.exe /iprange 10.10.10.2 10.10.10.254 /sjson 10.10.10.0.json /WindowsKeys 1 /OfficeKeys 1 /SQLKeys 1 /IEKeys 0 /ExchangeKeys 1 /ExtractEdition 0 Используемые параметры
/iprange - указывает диапазон адресов для сканирования /sjson - файл отчета необходимо сохранить в формате json /WindowsKeys 1 - собирать ключи операционных систем /OfficeKeys 1 - собирать ключи Office /SQLKeys 1 - собирать ключи SQL сервера /IEKeys 0 - НЕ собирать ключи IE /ExchangeKeys 1 - собирать ключи Exchange /ExtractEdition 0 - НЕ собирать расширенную информацию об операционной системе Это один из вариантов запуска, большее количество параметров описано на сайте разработчика.
После того, как утилита закончит свою работу, она сохранит отчет в формате json в указанный нами файл. Можно использовать и другие форматы отчетов, но явного представления о количестве и качестве мы не получим. Программа только собирает данные, все остальные манипуляции с ними ложатся на плечи рядовых администраторов.
Но не беда, на помощь нам приходит, уже затертый до дыр, Apache + PHP.
Все файлы отчета помещаем на машину, где установлены эти ребята, и обязательно за пределами Web сервера. Сам PHP скрипт будет выглядеть следующим образом.
<?PHP if(false) { ini_set('error_reporting', E_ALL); ini_set('display_errors', 1); ini_set('display_startup_errors', 1); } $myKeys = array( 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX' => 'Управляющая компания', 'YYYYY-YYYYY-YYYYY-YYYYY-YYYYY' => 'Завод №1', 'ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ' => 'Складская зона', ); $info = array(); /* Тут указываем путь и шаблон поиска файлов отчетов (Here we specify the path and template for finding report files) glob("../../../info/log_*.json") glob("/var/log/*.json"; glob("*.json"); */ foreach(glob("*.json") as $file) { $json = str_replace(array("\r\n", "\n"), '', file_get_contents($file)); $json = json_decode(iconv('cp1251', 'utf-8', $json), true); if(is_array($json)) { foreach($json as $id => $obj) { if(preg_match_all('/(.+) \((.+)\)/m', $obj['Computer Name'], $host)) { $ip =& $host[2][0]; $name =& $host[1][0]; $net = explode('.', $ip); array_splice($net, 3); array_push($net, '0'); if($ip == $name) $name = '<u>'.$name.'</u>'; $net = implode('.', $net); $info[$obj['Product Name']][$obj['Product Key']][$net][] = $ip.' ('.$name.')'; } } } } echo '<html lang="ru-RU" dir="ltr">'; echo '<head>'; echo '<style type="text/css">body {cursor: default;} i b:hover {color: forestgreen; text-decoration: underline;} #host:hover {color: forestgreen;}</style>'; echo '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>'; echo '</head>'; echo '<body>'; echo '<pre>'; $uSoft = 0; $uKey = 0; $uNet = 0; foreach($info as $software => $keys) { $uSoft++; echo "<b style='font-size: large; cursor: pointer;' onclick=\"if($('div#s".$uSoft."').is(':visible')) $('div#s".$uSoft."').hide(400); else $('div#s".$uSoft."').show(400);\">".$software."</b> <i style='font-size: normal;'>(licenses: ".count($keys).")</i>\n"; echo "<div id='s".$uSoft."' hidden>"; asort($keys); foreach($keys as $key => $subnet) { $uKey++; if(!$key) $key = 'UNKOWN'; echo "\t<i><b style='cursor: pointer; color: forestgreen;' onclick=\"if($('div#k".$uKey."').is(':visible')) $('div#k".$uKey."').hide(400); else $('div#k".$uKey."').show(400);\">".$key."</b> (hosts: ".(count($subnet, COUNT_RECURSIVE) - count($subnet)).")</i> <b style='color: red;'>".(isset($myKeys[$key])? $myKeys[$key] : '')."</b>\n"; echo "<div id='k".$uKey."' hidden>"; foreach($subnet as $net => $host) { $uNet++; echo "\t\t<i><b style='cursor: pointer;' onclick=\"if($('div#n".$uKey.$uNet."').is(':visible')) $('div#n".$uKey.$uNet."').hide(400); else $('div#n".$uKey.$uNet."').show(400);\">".$net."</b> (hosts: ".count($host).")</i>\n"; echo "<div id='n".$uKey.$uNet."' hidden style='padding-bottom: 10px;'>"; foreach($host as $name) echo "\t\t\t<span id='host'><i>".$name."</i></span>\n"; echo "</div>"; } echo "</div>"; } echo "</div>\n"; } echo '</pre>'; echo '</body>'; echo '</html>'; ?> Просто и сердито.
На выходе мы получаем каталогизированный список программного обеспечения, используемых ключей и списка хостов на которых были найдены эти ключи с сортировкой по сетям.
Также в скрипте можно указать список ключей и дать им имена.
$myKeys = array( 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX' => 'Управляющая компания', 'YYYYY-YYYYY-YYYYY-YYYYY-YYYYY' => 'Завод №1', 'ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ' => 'Складская зона', ); Удобно если требуется явно указать на какие подразделения или объекты приобреталась та или иная лицензия. Все совпадения будут выделены красной подписью.
Выводы
Из плюсов, это явная простота и стоимость данного решения. Начальную статистику можно получить уже через пару часов после поднятия вопроса о необходимости иметь результат еще вчера. Наглядность представления. Можно добавить расчет стоимости поддержания данного софта в "деревянных" или сразу в "бакинских", ну и естественно принять соответствующие меры, какие, решать уже Вам.
Из минусов, это не 100% результативность т.к статистика будет получена только по тем машинам, которые были онлайн на момент сканирования. Отсутствие системы кэширования для накопления данных при периодических опросах сети. Хотя последнее можно исправить средствами PHP, но пока такая задача не ставилась.
-
By Kitsum
Push уведомления - очень удобное, даже жизненно необходимое, дополнение к серверу. В любом месте на планете мы получаем оперативную информацию с поля боя.
Для реализации задуманного есть очень удобный ресурс pushbullet.com с простым API.
Забегая немного вперед, сразу покажу как это хозяйство будет выглядеть.
Android
Windows
На момент написания статьи, сервис поддерживает следующие платформы для получения push уведомлений:
Android iOS Windows Chrome Firefox Opera Safari Думаю, что в скором времени и Mac добавится к списку.
И так, к делу
Все работы я проводил на Linux Ubuntu Server 4.8 и Zabbix 2.4, но описанное подойдет для любой ОС семейства UNIX, а под Windows лишь с небольшими модификациями.
Первым делом нам необходимо перейти на сайт pushbullet (ссылка в начале поста) и пройти регистрацию или авторизоваться под одной из предоставленных систем: google, facebook ... В общем есть из чего выбирать.
Привязать необходимую платформу для получения уведомлений можно в разделе Devices -> Add device. Для установки Вас перенаправят на ресурс соответствующий вашему выбору. Устанавливаем, авторизуемся и возвращаемся на сайт в раздел Settings -> Account. Ищем графу Access Token и, если у Вас хорошая память, запоминаем или переписываем секретный ключ.
Самое тяжелое позади, переходим к изучению API
Необходимый багаж знаний мы можем получить в соответствующем разделе сайта docs.pushbullet.com
Раздел Pushes гласит, что мы можем отправлять запросы методом POST/GET и использовать следующие типы запросов с сопутствующими параметрами:
На момент написания статьи, ссылка по которой реализована работа с API выглядит так - https://api.pushbullet.com/v2/pushes
В документации приведен пример для отправки тестового push уведомления методом POST с использованием Curl в формате Json.
curl --header 'Authorization: Bearer <your_access_token_here>' \ -X POST https://api.pushbullet.com/v2/pushes \ --header 'Content-Type: application/json' \ --data-binary '{"type": "note", "title": "Note Title", "body": "Note Body"}' Для теста замените <your_access_token_here> на свой секретный ключ.
Это довольно удобно, но у меня возникли проблемы в реализации связки Zabbix -> Bash -> Curl+Json, при которой наблюдались перебои в работе. Поэтому я выкинул из связки Json.
Устремляемся на сервер
Идем в каталог со скриптами оповещений Zabbix (в Linux это /usr/local/share/zabbix/alertscripts) и создаем там файл с любым именем, но для удобства понимания назовем его pushbullet.
Это будет простенький Bash скрипт со следующим содержимым:
#!/bin/bash API_URL="https://api.pushbullet.com/v2/pushes" API_KEY="$1" SUBJECT="$2" MESSAGE="$3" curl $API_URL -u $API_KEY: -d type=note -d title="$SUBJECT" -d body="$MESSAGE" -X POST Переходим в Zabbix
В разделе Администрирование -> Способы оповещения и добавляем новый способ со следующими параметрами:
Имя - pushbullet Тип - Скрипт Имя скрипта - pushbullet Идем в раздел Настройка -> Действия -> Источник событий: Триггеры и создаем новое действие с именем Report problems to Pushbullet.
Активируйте и отредактируйте Сообщение по умолчанию и Сообщение о восстановлении, это поможет получать как список самих проблем так и сообщения при их устранении. Далее в разделе Операции указываем Тип операции: отправлять сообщение и выбираем отправлять только через pushbullet.
Можно отредактировать через стандартный шаблон оповещений, но отдельный шаблон позволяет создать конкретное сообщение, что очень удобно т.к например на телефоне не большой дисплей и плавать во всем шлаке данных о проблеме будет не удобно. Что выбрать решать только Вам.
Теперь самое вкусно. Переходим в раздел Администрирование -> Пользователи и выбираем нашу учетную запись. Во вкладке Оповещения добавляем новое оповещение со следующими параметрами:
Тип - pushbullet Отправлять на - указываем <your_access_token_here> Остальные параметры по желанию, но по личному опыту советую изменить активность на Ваше рабочее время. Я уже получал посреди ночи пулеметную очередь уведомлений с последующими одиночными выстрелами.
Таким образом настраиваются уведомления для всех необходимых пользователей.
Все готово к работе.
PS: По желанию Вы можете модифицировать скрипт и профили пользователей для получения уведомлений на конкретные устройства или распределить между устройствами оповещения в зависимости от текущего времени дня (на рабочий телефон в рабочее время, на домашний компьютер/телефон в свободное). Выбор остается за Вами.
-
-
Recently Browsing 0 members
No registered users viewing this page.