Модули
Начинать написание скрипта необходимо с объявления локальной переменной, которой присваивается вызов модуля.
Чтение и запись
Для чтения и записи значений тегов в скрипте необходимо вызвать модуль, соответствующий типу выполняемой функции.
local tagApi = require("simplight.api.channels") -- вызов модуля асинхронных функций чтения/записи
local async = require("async") -- вызов модуля асинхронного выполнения функций
local tagApiSync = require("simplight.api.channels.sync") -- вызов модуля синхронных функций чтения/записи (вызывать модуль async не требуется)
read
read(tagName: string): Channel
Принимает имя тега в виде строки и возвращает объект типа Channel, содержащий все основные данные о теге.
Объект Channel содержит следующие основные поля:
| Поле | Тип данных | Описание |
|---|---|---|
id |
int64 |
Уникальный идентификатор тега в системе |
name |
string |
Имя тега |
value |
any |
Текущее значение тега (может быть числом, булевым значением, строкой и т.д.) |
quality |
uint16 |
Код качества данных, указывающий на достоверность значения |
highScale |
float |
Максимальное значение диапазона шкалы тега |
lowScale |
float |
Минимальное значение диапазона шкалы тега |
loLoAlarm |
float |
Нижнее пороговое значение аварийного события |
loAlarm |
float |
Нижнее пороговое значение предупредительного события |
hiAlarm |
float |
Верхнее пороговое значение предупредительного события |
hiHiAlarm |
float |
Верхнее пороговое значение аварийного события |
alarmStatus |
enum AlarmStatus |
Текущий статус аварии для данного тега |
Пример:
Прочитать нижнее пороговое значение предупредительного события и текущее значение тега temp 1.
readValue
readValue(tagName: string): any
Возвращает текущее значение тега по его имени. Это упрощенная версия функции read, которая возвращает только значение, без других атрибутов тега.
Возвращаемое значение:
| Поле | Тип данных | Описание |
|---|---|---|
value |
any |
Текущее значение тега (может быть числом, булевым значением, строкой и т.д.) |
Пример:
Прочитать значение тега temp 2.
readMany
readMany(tagNames: string[]): Channel
Позволяет за один запрос получить данные (значение, качество, атрибуты тревог и т.д.) для списка тегов. Принимает массив имен тегов и возвращает объект типа Channel, содержащий все основные данные о теге.
Объект Channel содержит следующие основные поля:
| Поле | Тип данных | Описание |
|---|---|---|
id |
int64 |
Уникальный идентификатор тега в системе |
name |
string |
Имя тега |
value |
any |
Текущее значение тега (может быть числом, булевым значением, строкой и т.д.) |
quality |
uint16 |
Код качества данных, указывающий на достоверность значения |
highScale |
float |
Максимальное значение диапазона шкалы тега |
lowScale |
float |
Минимальное значение диапазона шкалы тега |
loLoAlarm |
float |
Нижнее пороговое значение аварийного события |
loAlarm |
float |
Нижнее пороговое значение предупредительного события |
hiAlarm |
float |
Верхнее пороговое значение предупредительного события |
hiHiAlarm |
float |
Верхнее пороговое значение аварийного события |
alarmStatus |
enum AlarmStatus |
Текущий статус аварии для данного тега |
Пример:
Прочитать значения тегов temp 1, temp 2, temp 3, temp 4.
write
write(tagName: string, value: any, quality: uint16)
Записывает данные в тег на сервере. Функция принимает имя целевого тега, значение и признак качества, которые необходимо записать.
Запись качества в физический тег можно опустить.
| Поле | Тип данных | Описание |
|---|---|---|
name |
string |
Имя тега |
value |
any |
Текущее значение тега (может быть числом, булевым значением, строкой и т.д.) |
quality |
uint16 |
Код качества данных, указывающий на достоверность значения |
Пример:
Записать значение (177) и признака качества (0xC0 — хорошее качество) в тег temp 3.
writeMany
writeMany(req: WriteChannelRequest)
Функция предназначена для массового обновления значений тегов. Если запись одного из тегов завершится ошибкой, функция продолжит попытки записать остальные теги из списка. После завершения итерации по всем тегам, если хотя бы одна операция записи не удалась, функция сгенерирует исключение, которое будет содержать информацию о том, какой конкретно тег вызвал ошибку.
В функцию передается аргумент в виде таблицы values со значениями нескольких тегов.
| Поле | Тип данных | Описание |
|---|---|---|
name |
string |
Имя тега |
value |
any |
Текущее значение тега (может быть числом, булевым значением, строкой и т.д.) |
quality |
uint16 |
Код качества данных, указывающий на достоверность значения |
Пример:
Записать значение и признака качества (0xC0 — хорошее качество) в теги temp 1, temp 2, temp 3, temp 4.
local async = require("async")
local tagApi = require("simplight.api.channels")
async(function()
await(tagApi.writeMany({
values={
{ name="temp 1", value=101, quality = 0xC0 },
{ name="temp 2", value=202, quality = 0xC0 },
{ name="temp 3", value=303, quality = 0xC0 },
{ name="temp 4", value=404, quality = 0xC0 },
}
}))
end)
Временные метки
Модуль time предоставляет функции для работы с временными значениями. Система использует Unix timestamp (временная метка) в миллисекундах, отсчитываемый от начала эпохи Unix (1 января 1970 года, 00:00:00 UTC). Все временные метки относятся к часовому поясу UTC (всемирное координированное время). Для работы с временными метками в скрипте, необходимо соответствующим образом оформить вызов:
from
from(tp: TimeParts): number
Конвертирует детализированное представление даты и времени в единую числовую временную метку в формате UTC. Возвращает число в виде Unix timestamp.
В качестве аргумента принимает таблицу TimeParts со следующими обязательными полями:
| Поле | Тип данных | Описание |
|---|---|---|
year |
number |
Год (четыре цифры) |
month |
number |
Месяц (1-12) |
day |
number |
День месяца (1-31) |
hour |
number |
Час (0-23) |
min |
number |
Минуты (0-59) |
sec |
number |
Секунды(0-59) |
msec |
number |
Миллисекунды(0-999) |
Пример:
Вернуть временную метку для даты 13.02.1981 и времени 04:30:45.500.
local time = require("time")
local timestamp = time.from({
year = 1981,
month = 02,
day = 13,
hour = 04,
min = 30,
sec = 45,
msec = 500
})
print("timestamp is:", timestamp)
now
now(): number
Возвращает временную метку, сформированную по текущим значениям времени системы в виде Unix timestamp.
Пример:
Вернуть текущую временную метку сервера.
toString
toString(timestamp: number): string
Преобразует временную метку в удобочитаемую строку с датой и временем.
Пример:
Вернуть текущую дату и время сервера в виде строки.
local time = require("time")
local nowStamp = time.now()
local nowString = time.toString(nowStamp)
print("current time is:", nowString)
toTable
toTable(timestamp: number): TimeParts
Выполняет обратное преобразование, разбирая единую временную метку на отдельные компоненты (год, месяц, день и т.д.).
Пример:
Вернуть значение текущего месяца и года сервера.
local time = require("time")
local nowStamp = time.now()
local nowTable = time.toTable(nowStamp)
print("current month and year:",nowTable.month, nowTable.year)
Архивные данные
Для работы с значениями тегов в базе данных необходимо вызвать соответствующий модуль:
getRange
getRange(options: GetOptions): []Moment
Получает архивные данные тега за указанный временной интервал.
В качестве аргумента передается таблица GetOptions:
| Поле | Тип данных | Описание |
|---|---|---|
channelName |
string |
Имя тега, для которого запрашивается история |
start |
timestamp |
Начальная временная метка |
ending |
timestamp |
Конечная временная метка |
Возвращаемое значение — массив Moment:
| Поле | Тип данных | Описание |
|---|---|---|
t |
timestamp |
Временная метка записи |
q |
quality |
Качество значения в момент записи |
v |
any |
Значение тега в момент записи |
Пример:
Необходимо выполнить анализ значений и признака качества тега "Напряжение" из базы данных за последние две минуты.
local momentApi = require("moments")
local async = require("async")
local time = require("time")
async(function()
local ending = time.now()
local start = ending - 2 * 60 * 1000
local ms = await(momentApi.getRange({
channelName = "Напряжение",
start = start,
ending = ending,
}))
for _, m in ipairs(ms) do
print(("{t: %d, v: %s, q: %d}"):format(m.t, m.v, m.q))
end
end)
getMin
getMin(options: GetOptions): number|nil
Вычисляет минимальное значение тега за указанный временной интервал на основе архивных данных. Если в указанном интервале нет архивных записей, функция возвращает nil.
В качестве аргумента передается таблица GetOptions:
| Поле | Тип данных | Описание |
|---|---|---|
channelName |
string |
Имя тега, для которого запрашивается история |
start |
timestamp |
Начальная временная метка |
ending |
timestamp |
Конечная временная метка |
getMax
getMax(options: GetOptions): number|nil
Вычисляет максимальное значение тега за указанный временной интервал на основе архивных данных. Если в указанном интервале нет архивных записей, функция возвращает nil.
В качестве аргумента передается таблица GetOptions:
| Поле | Тип данных | Описание |
|---|---|---|
channelName |
string |
Имя тега, для которого запрашивается история |
start |
timestamp |
Начальная временная метка |
ending |
timestamp |
Конечная временная метка |
getAverage
getAverage(options: GetOptions): number|nil
Вычисляет среднее арифметическое значение тега за указанный временной интервал на основе архивных данных. Если в указанном интервале нет архивных записей, функция возвращает nil.
В качестве аргумента передается таблица GetOptions:
| Поле | Тип данных | Описание |
|---|---|---|
channelName |
string |
Имя тега, для которого запрашивается история |
start |
timestamp |
Начальная временная метка |
ending |
timestamp |
Конечная временная метка |
save
save(ms: []TagMoment)
Сохраняет массив значений тегов в базу данных с текущей временной меткой.
В качестве аргумента передается массив TagMoment:
| Поле | Тип данных | Описание |
|---|---|---|
tagName |
string |
Имя тега, для которого сохраняется значение |
value |
any |
Значение для сохранения в архив (может быть числом, строкой, булевым значением) |
Пример:
Сохранить значения тегов в базе данных с указанием одинаковой метки времени. Этот подход может быть использован для формирования отчета на основе временной метки.
local async = require("async")
local momentApi = require("moments")
local tagApi = require("simplight.api.channels")
local events = require("simp-events")
local function doAction()
return async(function()
local currentTag = await(tagApi.read("Ток"))
local voltageTag = await(tagApi.read("Напряжение"))
local powerTag = await(tagApi.read("Мощность"))
await(momentApi.save({
{
tagName = "Ток",
value = currentTag.value,
},
{
tagName = "Напряжение",
value = voltageTag.value,
},
{
tagName = "Мощность",
value = powerTag.value,
}
}))
end):catch(function(err)
print("doAction: ", err)
end)
end
events.on("channelWrite", function(event)
for _, w in ipairs(event.writes) do
if w.name == "Действия.СделатьЗапись" then
doAction()
end
end
end)
Битовые операции
Для выполнения битовых операций в скрипте, необходимо вызвать модуль:
| Функция | Описание |
|---|---|
| band(x: number; y: number): number | Побитовое И над числами x и y |
| bor(x: number; y: number): number | Побитовое ИЛИ над числами x и y |
| bxor(x: number; y: number): number | Побитовое исключающее ИЛИ над числами x и y |
| bnot(x: number): number | Побитовое НЕ над числом x |
| lshift(x: number; n: number): number | Побитовое смещение влево числа x на n бит |
| rshift(x: number; n: number): number | Побитовое логическое смещение вправо числа x на n бит |
| arshift(x: number; n: number): number | Побитовое арифметическое смещение вправо числа x на n бит |
| getBit(x: number; bit: number): number | Возвращает 0 либо 1 в зависимости установлен ли бит bit в числе x* |
| setOnBit(x: number; bit: number): number | Возвращает число с установленным битом bit полученным от числа x* |
| setOffBit(x: number; bit: number): number | Возвращает число со снятым битом bit полученным от числа x* |
*Нумерация битов осуществляется справа налево, начиная с 1
Пример:
Выполнить операцию побитового И числел x и y.
local bitop = require("bitop")
local x = 5
local y = 6
local bitAnd = bitop.band(x, y)
print(bitAnd)
Файловая система
Для работы с файловой системой на сервере необходимо вызвать модуль:
appendFile
appendFile(filename: string; content: string)
Функция предназначена для последовательной записи данных в файл. Она открывает указанный файл и добавляет переданный контент в его конец, не изменяя уже существующее содержимое. В случае отсутствия файла по указанному пути, он будет создан автоматически.
Пример:
Создать каталог fsData, разместить в нем файл file.txt и в файл добавить строку "init message".
local fs = require("fs")
local basePath = "C:/SimpLight projects/fsData/file.txt"
fs.appendFile(basePath, "test message")
readFile
readFile(filename: string, options: table)
Получает доступ к содержимому файла, расположенного по указанному пути.
Пример:
Вычитать из файла file.txt его содержимое.
local async = require("async")
local fs = require("fs")
local basePath = "C:/SimpLight projects/fsData/file.txt"
async(function()
local content = await(fs.readFile(basePath))
print(content)
end)
writeFile
writeFile(filename: string, content: string)
Перезаписывает содержимое файла, расположенного по указанному пути.
Пример:
Полностью перезаписать содержимое файла file.txt.
local fs = require("fs")
local basePath = "C:/SimpLight projects/fsData/file.txt"
fs.writeFile(basePath, "new message")
mkdir
mkdir(path: string, options: MkdirOptions)
Создаёт каталог по пути path. В качестве аргумента принимает путь каталога и таблицу MkdirOptions:
| Поле | Тип данных | Описание |
|---|---|---|
recursive |
bool |
Необходимо установить в true для создания вложенных каталогов |
local async = require("async")
local fs = require("fs")
local basePath = "C:/SimpLight projects/fsData"
async(function()
await(fs.mkdir(basePath .. "/new_folder/new_subfolder", { recursive = true }))
end)
copyFile
copyFile(srcFilename, newFileName: string; failIfExists: bool)
Копирует указанный файл в новое местоположение. Флаг failIfExists позволяет прервать операцию, если файл уже существует.
Возвращаемое значение:
- true — файл успешно создан и скопирован.
- false — файл с указанным именем уже существует.
local async = require("async")
local fs = require("fs")
local basePath = "C:/SimpLight projects/fsData"
async(function()
await(fs.copyFile(basePath .. "/file.txt", basePath .. "/new_folder/2.txt", true))
end)
existsFile
existsFile(path: string)
Проверяет наличие файла. Следует отметить, что данную функцию не следует использовать перед чтением или открытием файла, так как это может привести к состоянию гонок. В этом случае между проверкой наличия файла и его открытием могут быть выполнены другие операции, такие как удаление файла или его открытие другим приложением с исключительными правами доступа, что может вызвать ошибку.
Возвращаемое значение:
- true — файл существует.
- false — файл не существует.
Пример:
Проверить наличие файла file.txt по указанному пути.
local async = require("async")
local fs = require("fs")
async(function()
local file_exist = await(fs.existsFile("C:/SimpLight projects/fsData/file.txt" ))
print(file_exist)
end)
existsDir
existsDir(path: string)
Определяет наличие каталога по указанному пути.
Возвращаемое значение:
- true — каталог существует.
- false — каталог не существует.
Пример:
Проверить наличие каталога fsData по указанному пути.
local async = require("async")
local fs = require("fs")
async(function()
local dir_exist = await(fs.existsDir("C:/SimpLight projects/fsData" ))
print(dir_exist)
end)
Пути
Для работы с путями в файловой системе на сервере необходимо вызвать модуль:
dirname
dirname(path: string): string
Возвращает имя каталога по указанному пути.
local path = require("path")
local async = require("async")
async(function()
local dir = await(path.dirname("C:/SimpLight projects/fsData/"))
print("Имя каталога: ", dir)
end)
basename
basename(path: string; suffix: string): string
Возвращает последнюю часть указанного пути. Если указать suffix, то он будет удален с конца строки.
local async = require("async")
local path = require("path")
local basePath = "C:/SimpLight projects/fsData"
async(function()
local last_path = await(path.basename(basePath, "ta")) -- исключение суффикса "ta" из строки пути
print("Последняя часть пути: ", last_path) --> fsDa
end)
extname
extname(path: string): string
Возвращает расширение файла по указанному пути.
local path = require("path")
local async = require("async")
async(function()
local ext = await(path.extname("C:/SimpLight projects/fsData/file.txt"))
print("Расширение файла: ", ext)
end)
join
join(paths: []string): string
Корректно объединяет несколько сегментов в единый путь, учитывая особенности файловой системы платформы. После соединения функция выполняет нормализацию пути, удаляя лишние разделители. Пустые строки в массиве игнорируются.
local path = require("path")
local async = require("async")
local basePath = "C:/SimpLight projects/fsData"
async(function()
local conc_path = await(path.join({basePath, "file.txt"}))
print(conc_path)
end)
События
Модуль для обработки системных событий в реальном времени. Для работы с событиями в скрипте, необходимо сделать вызов модуля:
channelChanges
changes: ChannelChange[]
Получает уведомления об изменениях значений всех тегов в системе.
Поля ChannelChange:
| Поле | Тип данных | Описание |
|---|---|---|
channelID |
int64 |
Идентификатор тега |
name |
string |
Имя тега |
quality |
uint16 |
Код качества данных, указывающий на достоверность значения |
value |
any |
Новое значение тега |
alarmStatus |
enum alarmStatus |
Текущий статус аварии для данного тега |
Пример:
Необходимо производить расчет потребляемой мощности при каждом изменении значений тегов Ток и Напряжение.
local events = require("simp-events") -- вызов модуля для работы с событиями
local tagApi = require("simplight.api.channels") -- вызов модуля асинхронных функций чтения/записи
local async = require("async") -- вызов модуля асинхронного выполнения функций
local function doVoltageAmperageChange() -- объявление функции вычисления мощности
async(function()
local voltageTag = await(tagApi.read("Напряжение")) -- извлечение значения тега "Напряжение"
local amperageTag = await(tagApi.read("Ток")) -- извлечение значения тега "Ток"
local power = voltageTag.value * amperageTag.value -- рассчет значения тега "Мощность"
await(tagApi.write("Мощность", power, 0xC0)) -- запись рассчитанного значения в тег
end):catch(function(err) -- обработка возможных ошибок
print("ошибка", err)
end)
end
events.on("channelChanges", function(event) -- подпишемся на событие channelChanges
for _, c in ipairs(event.changes) do
if c.name == "Напряжение" or c.name == "Ток" then -- если произошли изменения значений в тегах "Напряжение" или "Ток"
doVoltageAmperageChange() -- вызываем функцию вычисления мощности
end
end
end)
channelWrite
ChannelWriteEvent
Получает уведомления о записях значений во все теги системы.
Структура события:
- caller: EventCaller — информация об инициаторе записи.
- writes: WriteValue[ ] — массив записываемых значений.
Поля EventCaller:
| Поле | Тип данных | Описание |
|---|---|---|
connID |
string |
Идентификатор соединения |
userName |
string |
Имя пользователя |
Поля WriteValue:
| Поле | Тип данных | Описание |
|---|---|---|
channelID |
int64 |
Уникальный идентификатор тега |
name |
string |
Имя тега |
quality |
uint16 |
Качество для записи |
value |
any |
Значение для записи |
Пример:
Необходимо установить новые значения мощности для насосов Pump1 и Pump2 в случае записи в тег Действия.ОбновитьПеременные.
local events = require("simp-events") -- вызов модуля для работы с событиями
local tagApi = require("simplight.api.channels") -- вызов модуля асинхронных функций чтения/записи
local async = require("async") -- вызов модуля асинхронного выполнения функций
local function doActionUpdateVarsWrite() -- объявление функции обновления значений тегов "Pump1.FeedPower" и "Pump2.FeedPower"
async(function()
await(tagApi.write("Pump1.FeedPower", 100, 0xC0)) -- запись значения 100 и признака качества в тег "Pump1.FeedPower"
await(tagApi.write("Pump2.FeedPower", 75, 0xC0)) -- запись значения 75 и признака качества в тег "Pump2.FeedPower"
end)
end
events.on("channelWrite", function(event) -- подпишемся на событие channelWrite, чтобы отслеживать запись в теги
for _, write in ipairs(event.writes) do
if write.name == "Действия.ОбновитьПеременные" then -- если произошла запись значения в тег "Действия.ОбновитьПеременные"
doActionUpdateVarsWrite() -- вызываем функцию обновления значений тегов
end
end
end)
Глобальные переменные
Предоставляет постоянное хранилище типа "ключ-значение" на локальном диске (HDD/SSD) для скриптов. Объект localStorage позволяет сохранять строковые данные между запусками скриптов и перезагрузками системы. Использование объекта не требует вызова модуля.
setItem
setItem(key: string, value: string)
Метод сохраняет строковое значение по указанному ключу.
getItem
getItem(key: string): (string | nil)
Метод получает значение по указанному ключу.
removeItem
removeItem(key: string)
Метод удаляет пару "ключ-значение" по указанному ключу.
clear
clear()
Метод clear() полностью очищает хранилище, удаляя все сохраненные пары "ключ-значение".
getNumberDef
getNumberDef(key: string, default: number): number
Возвращает числовое значение по указанному ключу key. Если значение отсутствует, то по умолчанию возвращается значение default.
Отчеты
reports
buildReport(options: ReportBuildOptions)
В качестве аргумента в функцию передается структура параметров:
ReportBuildOptions
templatePath: string— путь к файлу шаблона отчета в системе.variables: ReportBuildVariables— пользовательские переменные для подстановки в шаблон.dataSources: ReportBuildDataSources— настройки источников данных отчета.actions: ReportBuildActions— действия после формирования отчета.
Таблица пользовательских переменных (ключ-значение).
{[name: string]: any}
- Ключ — имя переменной (строка).
- Значение — любое значение (строка, число, дата и т.д.).
Настройки источников данных отчета.
{[dataSourceName: string]: ChangeDataSourceParams | PeriodDataSourceParams}
- Ключ — имя источника данных в шаблоне (строка).
- Значение — параметры для источника данных одного из двух типов.
ChangeDataSourceParams:
Параметры для источников данных, основанных на изменениях.
start: time— начало временного диапазона (опционально).end: time— конец временного диапазона (опционально).
PeriodDataSourceParams:
Параметры для источников данных с периодической выборкой.
start: time— начало временного диапазона (опционально).end: time— конец временного диапазона (опционально).interval: time— интервал между выборками в миллисекундах (опционально).
Действия, выполняемые после успешного формирования отчета.
print: PrintActionOptions— параметры для печати отчета (опционально).save: SaveActionOptions— параметры для сохранения отчета в файл (опционально).show: ShowActionOptions— параметры для показа отчета пользователям (опционально).
PrintActionOptions:
enabled: boolean— включить ли печать отчета.targetUsers: []string— массив имен пользователей, которым доступна печать.
SaveActionOptions:
filepath: string— путь для сохранения файла отчета.
ShowActionOptions:
enabled: boolean— включить ли показ отчета.targetUsers: []string— массив имен пользователей, которым будет показан отчет.
Пример: