Макросы: Событийная система (Smart)
Макросы (или скрипты) — это мощнейший внутренний механизм автоматизации агрегаторов SIM Roulette. С помощью макросов могут быть реализованы абсолютно любые сценарии работы. При этом очень важно, что написание макросов доступно даже пользователям не знакомым с программированием, макросы не требуют компиляции (предварительного перевода в машинные коды), всегда готовы к исполнению и доступны для редактирования.
Устройство макроса
Синтаксис
Первые шаги
Полезные приемы
Примеры
Устройство макроса
Строки в макросе выполняются последовательно сверху вниз. Для изменения порядка выполнения применяются метки, операторы ветвления и безусловного перехода.
Метка - любое слово латиницей обрамленное квадратными скобками, ставится над строкой на которую должен быть осуществлен переход.
Пример метки: [next]
Текст макроса не должен содержать пустых строк. Каждая команда макроса может сопровождаться комментарием, отделенным от команды символами.
При запуске макроса через Терминал можно передать ему входные параметры m.my_macros:Текст_для_передачи_макросу Строка после : поступит в буфер, а дальше может быть разобрана стандартными методами работы с буфером.
Макросы размещаются в папке /m файловой системы.
Сложные макросы представляют собой комплексы файлов, в этом случае целесообразно хранить их в одной папке. При запуске макроса через терминал достаточно указать имя папки, SR найдет и запустит одноименный файл внутри указанной папки. При наличии макроса m/scanner/scanner его можно запустить как командой m.scanner/scanner так и m.scanner.
Также целесообразно снабжать сложные комплексы макросов файлом-руководством в формате макроса (среди примеров есть образец) с именем help и файлом-меню если предполагается запуск различных макросов из набора (пример также есть).
Синтаксис
Операторы ветвления
if — Проверяет результат выполнения предыдущей команды. Если результат равен 1 — осуществляется переход к указанной метке.
var:a<10
if next
...
[next]
...
unless — Проверяет результат выполнения предыдущей команды. Если результат равен 0 (NULL/Пустой) — осуществляется переход к указанной метке.
unless next
Оператор безусловного перехода
goto — Осуществляет переход к указанной метке.
goto next
...
[next]
...
Операторы завершения программы
stop — Завершение работы макроса.
stop
return — Производит досрочный возврат из вложенного макроса (по умолчанию возврат происходит после выполнения команды в последней строке вложенного макроса).
return
return:event — Производит досрочный возврат из макроса, вызванного событием.
return:event
Оператор ввода
input — Производит запрос действия сотрудника-оператора в разделе WEB-интерфейса Оператор. Параметры: максимальная длина вводимых данных;текст который будет выведен оператору над полем ввода).
input 1;Выберите действие:<br>1-первый вариант<br>2-второй вариант
Операторы выполнения команды из буфера
exec Выполняет команду из буфера (текст помещенный в буфер будет передан на выполнение как команда).
buffer>write=sound:beep
exec
exec2 Выполняет команду из копии буфера в стеке.
buffer>write=sound:beep
buffer>push
exec2
Оператор подключения вложенного макроса
include Подключает указанный макрос и передает ему управление (степень вложенности макросов неограничена), по окончании управление возвращается в текущий макрос.
include macrosname
Пауза
pause Пауза (приостановка программы) в миллисекундах (1/1000 секунды)
pause 1000
Первые шаги
Что же из себя представляет макрос или скрипт? Это набор команд агрегатору (все команды к вашему устройству подробно описаны в соответвующем разделе Документации). Например, вывести Hello world! в Терминал можно командой @echo:Hello world!. Но нас интересует другая команда: .ussd:{"number":"*102#","modem":"1"} — команда для осуществления USSD-запроса (в данном случае запроса баланса) для одной из СИМ-карт первого модема. Эта же команда может выглядеть так: .ussd:*102#,1, но в дальнейшем мы будем писать команды в JSON. Так нагляднее.
Давайте попробуем написать наш первый макрос. Для этого перейдем в раздел Макросы WEB-интерфейса вашего устройства и нажмем кнопку «Создать макрос». В поле «Название» введем my_macro. А в поле «Содержание»:
.ussd:{"number":"*102#","modem":"1"}
Макрос готов. Команда отправляет USSD-команду на 1 модем для запроса баланса. Вот так просто мы уже произвели небольшую автоматизацию. Теперь надо сохранить макрос нажав соответствующую кнопку.
Точку перед командой ussd необходимо ставить если мы хотим получить ответ о выполнении команды в выходной поток (в Терминал и на на управляющий сервер). Если мы не ставим точку, команда точно также выполняется, но без ответа.
Как запустить (выполнить) макрос. Через WEB-интерфейс макрос можно запустить двумя способами:
- В разделе Макросы, в списке найти строку с названием нужного макроса и нажать на иконку исполнения. Строка запущенного на исполнение макроса подсветится, к иконкам добавится новая — иконка остановки.
- В разделе Терминал ввести команду macro: и название вашего макроса — macro:my_macro. Существует также сокращенная команда m — m:my_macro. Запуск через терминал позволяет передать макросу входные данные. Делается это так m:my_macro:Текст_для_передачи_макросу.
Как остановить макрос. Для прерывания работы макроса также существуют 2 способа:
- В разделе Макросы, в списке найти строку с названием запущенного макроса и нажать на иконку остановки.
- В разделе Терминал ввести команду macro.stop. Существует также сокращенная команда m.stop.
Итак, выберите одну из установленных в устройство карт, дождитесь пока она станет активной и запустите любым способом ваш первый макрос. Получилось? Макрос должен был выполнить USSD-запрос. А результат выполнения вы можете увидеть в Терминале.
Давайте вернемся к редактированию (иконка редактирования в строке с названием макроса) и добавим дальнейший функционал. Мы ведь не собираемся вручную переключать карты и дожидаться пока они зарегиструются в сети. Здесь нам сразу же придет на помощь событийная система нашего агрегатора.
m.event:event=modemState,macro=my_macro:test,action=add
[test]
.ussd:{"number":"*102#","modem":"1"}
Добавилось 2 строки.
Команда в первой строке заставляет наш агрегатор постоянно отслеживать событие modemState (изменение состояния модемов) и при любом его изменении запускать указанный нами макрос my_macro с метки test [слово в квадратных скобках из второй строки]. После запятой action=add означает, что мы добавляем нового слушателя события modemState. Если мы передумаем и захотим перестать отслеживать событие — нужно будет подать команду m.event:event=modemState,macro=my_macro:test,action=delete.
Как же это работает? Выбирая карту из списка вы отключаете от модема текущую карту и подключаете к нему выбранную. В этот момент устройство перезапускает модем, чтобы он мог начать работу с новой СИМ-картой. Статус модема меняется на -1. Вот именно изменение этого статуса мы и просим наш агрегатор отслеживать.
Как только статус изменился, устройство просматривает список слушателей данного события и вызывает по очереди указанные макросы. Постепенно дело доходит и до нашего макроса. И вот уже макрос запущен. Но запущена команда следующая ниже метки test. Давайте же добавим эту и последующие команды.
m.event:event=modemState,macro=my_macro:test,action=add
[test]
buffer.test:-1
if end // Если статус -1 (СИМ-карта еще неактивна) - завершаем обработку события
buffer.test:1
if task // Если статус 1 (все в порядке, СИМ-карта в сети) - выполняем действие
buffer.test:3
if task // Если статус 3 (нет регистрации в сети) - предполагаем, что авторизация все-таки состоится и выполняем действие
buffer.test:5
if task // Если статус 5 - выполняем действие
buffer.test:6
unless end // Если статус (0,4), то есть не равен 6 (карта отсутствует) - завершаем обработку события
[end]
@echo: Подключение к сети...
return:event // Завершаем обработку события
[task]
buffer.event.dev
buffer.test:1 // Проверяем первый ли модем вернул статус
unless end // Это был не первый модем, поэтому завершаем обработку события
.ussd:{"number":"*102#","modem":"1"}
Разберем новые строки:
Прежде всего следует обратить внимание на фразы отделенные двумя наклонными чертами "//" от команд — это комментарии. Все что написано после косых черт не относится к программе, никак не интерпретируется обработчиком макросов и служит только для пояснения кода.
Второе — это операторы ветвления if и unless. Как они работают?
Операторы ветвления обрабатывают ответ предыдущей команды. Если ответ положительный 1 или некий текст, то выполняется условие оператора if и действие передается на метку указанную после оператора, для оператора unless наоборот условие не выполняется и действие уходит на следующую после оператора строку. Если ответ отрицательный 0(NULL), то условие оператора if не выполняется и действие уходит на следующую после оператора строку, а действие unless выполняется и действие передается на указанную после оператора метку.
Теперь вы можете самостоятельно разобрать этот кусок кода и проследить при каких статусах действие макроса продолжится с метки task, а при каких остановится после метки end. Тут следует отметить, что выход из макроса запущенного обработчиком события осуществляется по команде return:event. В следующий раз наш макрос будет вызван на выполнение с метки test при новом изменении статуса.
И вот мы могли бы уже запустить команду получения баланса. Но! Мы ведь помним, что в нашем устройстве 3 активных модема. А по коду выше мы проверили статус, но не проверили какой из модемов вернул этот статус. Вот и проверим. Получаем устройство командой buffer.event.dev и с помощью оператора ветвления решаем дальнейший ход событий. Итак, при получении соответствующего нашей задачи статуса и номера модема мы, наконец, запускаем команду получения баланса return:event. Полдела сделано. Теперь надо установить слушателя ответов USSD. Что мы и сделаем командой m.event:event=ussd,macro=my_macro:ussd,action=add. Этот механизм нам уже должен быть понятен, поэтому сразу добавляем выход return:event, метку ussd и пишем следующую часть программы:
m.event:event=modemState,macro=my_macro:test,action=add
[test]
buffer.test:-1
if end // Если статус -1 (СИМ-карта еще неактивна) - завершаем обработку события
buffer.test:1
if task // Если статус 1 (все в порядке, СИМ-карта в сети) - выполняем действие
buffer.test:3
if task // Если статус 3 (нет регистрации в сети) - предполагаем, что авторизация все-таки состоится и выполняем действие
buffer.test:5
if task // Если статус 5 - выполняем действие
buffer.test:6
unless end // Если статус (0,4), то есть не равен 6 (карта отсутствует) - завершаем обработку события
[end]
@echo: Подключение к сети...
return:event // Завершаем обработку события
[task]
buffer.event.dev // Запрашиваем номер устройства, вернувшего результат
buffer.test:1 // Проверяем первый ли модем вернул статус
unless end // Это был не первый модем, поэтому завершаем обработку события
.ussd:{"number":"*102#","modem":"1"}
m.event:event=ussd,macro=my_macro:ussd,action=add
return:event
[ussd]
buffer.find: *руб
if next // Ишем в текcте ответа на USSD-запрос фрагмент, например: " 53 руб"
return:event
[next]
@buffer // Если фрагмент найден выводим на экран найденный баланс
m.event:event=ussd,macro=my_macro:ussd,action=delete // Убираем слушателя
return:event
Разберем новые строки:
Событие USSD вызывает наш макрос с метки ussd. Макрос ищет в буфере сумму нашего баланса. Если не находит, мы завершаем процесс и оставляем слушателя USSD, хотя он уже не актуален. Вот вам и домашнее задание по доработке макроса ;)
А если баланс получен, мы выводим его в выходной поток командой @buffer, убираем слушателя USSD, но оставляем слушателя modemState. В этом случае при переключении любой карты ряда A, опять запустится наш запрос баланса.
Ну вот и все, теперь вы умеете писать макросы для SIM Roulette. Ознакомьтесь с синтаксисом макросов, почитайте документацию для SR-OPrganizer-Smart, посмотрите примеры макросов. А когда напишите полезный макрос можете поделиться им с другими бесплатно либо выставить на продажу.
Полезные приемы
Оформление текста
В тексте выводящимся в выходной поток терминала можно использовать следующую мнемонику для трансформаций:
[br] — перевод строки
[b]жирный текст[/b]
[i]курсив[/i]
Таблицы
Данные в выходной поток Терминала можно выводить в виде таблицы для этого используется следующий синтаксис (для удобства воcприятия он разложен по строкам, но в макросе текст команды всегда вводится одной строкой):
[table]
[tr]
[th]Заголовок 1-го столбца[/th]
[th]Заголовок 2-го столбца[/th]
[/tr]
[tr]
[td]Содержимое 1-го столбца[/td]
[td]Содержимое 2-го столбца[/td]
[/tr]
[/table]
Переход на другую страницу WEB-интерфейса/Перезагрузка страницы
Для перехода на любой _URL_ в текст, выводящийся в выходной поток Терминала (командами echo или buffer), необходимо вставить команду sr>reload_URL_; Не забываете про "." и "@" в начале команды.
buffer.write:sr>reload/terminal;
@buffer
@echo:sr>reloadhttps://google.com;
Очистка выходного потока Терминала
Для очистки выходного потока Терминала в текст необходимо вставить команду sr>clear;
buffer.write:sr>clear;
@buffer
@echo:sr>clear;
Эмуляция ручного ввода команды и ее исполнение
Для исполнения любой команды (_COM_) в любое место текста, выводящегося в выходной поток Терминала (командами echo или buffer), необходимо вставить команду sr>com:_COM_; Команда будет выполнена и останется в логе команд.
buffer:sr>com:version;
@buffer
@echo:version;
Вывод текста в поле ввода команды Терминала
Для вывода произвольного текста (_TEXT_) в поле для ввода команды Терминала в любое место текста, выводящегося в выходной поток Терминала (командами echo или buffer), необходимо вставить команду sr>enter:_TEXT_; После вставки текста в поле для ввода команды туда же переместится фокус браузера.
buffer:sr>version;
@buffer
@echo:sr>text:version;
Гиперсылки
Для удобства навигации вместо или наряду со списком команд можно выводить готовые гиперссылки содержащие команды. Для этого в любое место текста, выводящегося в выходной поток Терминала (командами echo или buffer), вставляются конструкции [link]_КОМАНДА_[name]_НАЗВАНИЕ_[/name][/link]
buffer:sr>Команда [link]version[name]Версия[/name][/link]
@buffer
@echo>sr>Команда [link]version[name]Версия[/name][/link]
Примеры
autoexec
Автозапуск фонового получения номеров СИМ-карт.
m.event:event=modemState,macro=scanner:test,action=add // Добавлем слушателя события modemState
com_add
Макрос для добавления в Терминал кнопок быстрых ссылок.
buffer.swap // Меняем буфер и копию местами
buffer.file.load:/terminal.dat // Загружаем в буфер текущее содержание кнопок
buffer.merge: // Склеиваем буфер и копию буфера
buffer.postfix:; // Добавляем в конец буфера ;
buffer.file.save:/terminal.dat // Сохраняем отредактированный файл
buffer.write:Command added // Готовим уведомление о том, что кнопка добавлена
@buffer // Выводим уведомление
pause 1000 // Ждем секунду
@echo:sr>reload/terminal; // Обновляем окно Терминала