Найти тему

Урок 2. SLS. Введение в LUA

Оглавление

Всем здрасте!

Сегодня скажу пару слов о LUA. Рассмотрим типы данных. Как их хранить в переменных. Область видимости переменных. Ну и так, по мелочи :)

Автоматизации в умном доме на базе шлюза SLS Gateway, рано или поздно сводятся к разработке скриптов на языке LUA. Кончено, разработчик обещает нам натыкивание автоматизаций мышкой аж с ноября 2021 года и если верить всем известной поговорке Сценарии должны случиться к концу настоящего года. Посмотрим. А пока, будем рассчитывать только на себя и эффективно пользоваться тем что есть.

Lua - достаточно мощный скриптовый язык программирования. Не вижу смысла копипастить или рерайтить здесь содержимое википедии и множества других подобных ресурсов. Скажу лишь о том, что если вы хотите продвинуться в разработке автоматизаций, то подобные ресурсы следует изучить. Хотя бы по диагонали, чтобы иметь представление о чем речь и в нужный момент к ним обратиться.

Многие пользователи требуют от документации на шлюз полный референс и на встроенные в язык функции в том числе. Интересно, в документации на автомобиль, также имеется полное описание команд процессора бортового компьютера, например? Уверен, что нет. Поэтому, подразумевается, что специалист, который пришел изучать референс по функциям LUA шлюза, уже осовил референс самого языка.

Параллельно с чтением моих статей рекомендую осилить:
- книгу по LUA, например
эту
-
референс по функциям, поддерживаемых прошивкой SLS
- да и в целом
документацию, хотя бы разок прочесть прям необходимо

Что же такое LUA

Со стороны шлюза или прошивки его MCU ESP32, язык - это набор функций, которые можно вызывать с помощью интерпретируемых сценариев LUA. Например, вы пишете print("Привет Мир!"), а интерпретатор "понимает", что параметр функции в виде текста, нужно отправить в STDOUT. Интерпретатор - это часть прошивки на языке С. Функции поддерживаются как нативные, например математической библиотеки math, так и специальные, для взаимодействия с подсистемами шлюза.

Инструменты разработки

Основной инструмент разработки находится в веб-интерфейсе управления, меню Actions -> Files. Мы его уже разбирали в этом видео. Этот инструмент, кроме управления файлами, позволяет создавать, удалять, редактировать и запускать скрипты на исполнение. Имеет подсветку синтаксиса и STDOUT - панель Output.

Заметили, я зачастил с STDOUT? Вот опять :). Просто почему-то большинство новичков упускает такой мощный инструмент отладки как STDOUT и функцию print().

Итак, результаты штатной работы скрипта можно выводить в лог указанной функцией. При отладке данная функция помогает "увидеть" что же у вас хранится в переменной, на определенном шаге выполнения скрипта.

Панель Output
Панель Output

В примере мы видим инкремент переменной а и на каждом шаге вывод ее значения в панель Output и Log

Log
Log

А если в работе скрипта возникает ошибка, мы ее также можем увидеть в STDOUT

Панель Output
Панель Output
Log
Log

В тексте ошибки мы видим, что возле символа а в 26 строке кода есть ошибка. В данном случае ошибка в синтаксисе функции print()

Так что, в любой непонятной ситуации, print() и STDOUT - наше всё!

Как писать код

Форматирование

Для интерпретатора код - это строка, поэтому всё оформление нужно только для удобства восприятия. Обратите внимание, все три варианта для интерпретатора одинаковы:

-6

Заметьте, что первый вариант можно использовать в правилах SimpleBind. То есть, не обязательно создавать файл скрипта, а достаточно код оформить в одну строку и вставить в правило с лидирующей # Например:

-7

Иногда, в сложных случаях, требуется поколдовать с кавычками.

Комментарии

Поддерживаются как однострочные, так и многострочные или блочные комментарии. Любые комментарии начинаются с двух дефисов "--". Выше, в примере оформления все варианты уже показаны. Есть небольшой лайфхак. Например, вы написали блок кода и желаете проверить этот же код, с небольшими изменениями. Для этого обрамляете оба блока блочными комментариями. Для раскомментирования блока, достаточно поставить всего один дефис:

-8

Как видите, второй блок раскомментирован всего лишь добавлением одного дефиса перед блоком.

Переменные

Типы данных

Lua представляет собой язык с неявным динамическим определением типов данных. Переменная языка может содержать значения любого типа. Все значения в Lua могут храниться в переменных, использоваться в качестве аргументов при вызове функций и возвращаться в виде результата их выполнения.

В Lua восемь основных типов:
-
nil (неопределенный)
-
boolean (логический)
-
number (числовой)
-
string (строковый)
-
function (функция)
-
userdata (пользовательские данные)
-
thread (поток)
-
table (таблица или массив)

Подробно останавливаться на описании типов не будем. А поговорим о нюансах.

nil - это тип значения [пустое значение], главное свойство которого - отличаться от всех остальных значений и обозначать отсутствие пригодного значения. Если при объявлении переменной, ей не присваивается значение, то значение как раз и будет nil.

boolean и string - соответственно логические (boolean): true (истина) и false (ложь), а также строковые (string).

true - это boolean
"true" - это string

Как бы это не было банально, но новички часто путают true и "true". И оба варианта считают либо строкой, либо логическим значением. Будьте внимательны.

Кстати, кавычки тоже могут быть разные: "string" и 'string'. В большинстве случаев не важно - одинарные они или двойные. Более подробно нюансы использования разных кавычек обсудим в другой раз.

Поскольку переменная связывается с типом в момент присваивания значения, а не в момент объявления переменной, то не всегда очевидно, какой тип фактически хранится в переменной. Проверить тип можно функцией type()

-9

Объявление переменных и видимость

Именами (идентификаторами) переменных в Lua могут быть любые последовательности из букв, цифр и символа подчеркивания, начинающиеся не с цифры. Также, различается регистр символов, поэтому abc, Abc, ABC являются различными именами.

Глобальная переменная появляется в момент присваивания ей первого значения и существует до тех пор, пока существует среда исполнения скрипта и доступна любому Lua-коду, выполняемому в этой среде. В SLS каждый скрипт выполняется в своем отдельном потоке (среде). После выполнения скрипта все его переменные удаляются. Поэтому глобальные переменные в SLS видны только внутри скрипта, в котором они объявлены. До присваивания первого значения обращение к глобальной переменной даёт nil. При необходимости удалить глобальную переменную можно явным образом, просто присвоив ей значение nil.

-10

Локальные переменные должны быть объявлены явно с использованием ключевого слова local. Объявить локальную переменную можно в любом месте скрипта. Объявление может включать в себя присваивание переменной начального значения. Если значение не присвоено, переменная содержит nil. При необходимости удалить локальную переменную можно явным образом, присвоив ей значение nil.

-11

Область видимости локальной переменной начинается после объявления и продолжается до конца блока.

Под блоком понимается:
- тело управляющей конструкции (if-then, else, for, while, repeat)
- тело функции
- фрагмент кода, заключённый в ключевые слова do...end

Если локальная переменная определена вне какого-либо блока, её область видимости распространяется до конца скрипта.

-12

Использовать или нет локальные переменные, решать вам. Но я бы посоветовал, по возможности всегда использовать локальные, а глобальные - только там, где это действительно необходимо. А чтобы выбор было сделать легче, верьте в то, что с локальными переменными чуть выше производительность :)

Домашнее задание

Попробовать осилить референс по функциям, поддерживаемых прошивкой SLS. Хотя бы скачать и полистать книгу по LUA, например эту.

Что дальше

На следующем уроке будем проходить условные ветвления и логику. Так что подписывайтесь, читайте, ставьте лайки и пишите комментарии. Делайте ДЗ. Пока, пока!

----------
Листинги скриптов
Поддержать канал
Заказать обучение
Поболтать