Перейти к содержанию

Время наработки тега

Рассмотрим пример добавления пользовательской библиотеки. Для этого поместим модуль, написанный на языке Lua, в рабочий каталог программы.

Например, для решения задачи подсчета времени наработки агрегата в системе требуется создать скрипт с именем motoHours.lua, а затем разместить его в специально созданном каталоге для пользовательских библиотек, например, с именем lib. Данный каталог должен быть расположен по пути: C:\Users\Public\Documents\SimpLight_5.0\scripts\sdk.

motoHours.lua
local async = require("async")
local tagApi = require("simplight.api.channels")
local time = require("time")
local promise = require("promise")

local function timeSince(t)
  local elapsedTime = time.now() - t
  return elapsedTime
end

local function localStorage_getNumberDef(key, default)
  local v = localStorage:getItem(key, default)
  if v == nil then
    return default
  end

  return tonumber(v)
end

local function composeLabel(tagName)
  return string.format('$simplight.motoHours.%s.totalWorkTime', tagName)
end

local M = {}
local watchByTagNameMap = {}

local function checkTag(tagName, tagValue)
  local watch = watchByTagNameMap[tagName]
  if watch == nil or watch.isCalcing then
    return promise.resolve(true)
  end

  return async(function()
    watch.isCalcing = true
    local label = composeLabel(watch.watchTagName)
    local totalWorkTime = localStorage_getNumberDef(label, 0)

    local v = watch.valueGetter(tagValue)
    if v == 1 or v == true then
      if not watch.isRun then
        watch.lastUpdateTime = time.now()
        watch.isRun = true
      end

      totalWorkTime = totalWorkTime + timeSince(watch.lastUpdateTime)
      watch.lastUpdateTime = time.now()
    else
      if watch.isRun then
        totalWorkTime = totalWorkTime + timeSince(watch.lastUpdateTime)
        watch.lastUpdateTime = 0
        watch.isRun = false
      end
    end

    if watch.resetTagName ~= '' then
      local resetTag = await(tagApi.read(watch.resetTagName))
      if resetTag.value then
        totalWorkTime = 0
        watch.lastUpdateTime = 0
        watch.isRun = false
        await(tagApi.write(watch.resetTagName, 0, 0xC0))
      end
    end

    watch.totalWorkTime = totalWorkTime

    localStorage:setItem(label, totalWorkTime)
  end):catch(function(err)
    print("MotoHours.checkTag:", err)
  end):finally(function()
    watch.isCalcing = false
  end)
end

function M.watch(options)
  local watchTagName = options.watchTagName

  if type(watchTagName) ~= "string" then
    error("motoHours.watch: watchTagName must be string")
  end

  local label = composeLabel(watchTagName)
  local totalWorkTime = localStorage_getNumberDef(label, 0)

  local lWatch = {
    lastUpdateTime = 0,
    isRun = false,
    resetTagName = options.resetTagName,
    valueGetter = options.valueGetter,
    totalWorkTime = totalWorkTime,
    watchTagName = watchTagName,
  }

  if valueGetter == nil then
    lWatch.valueGetter = function(srcValue)
      return srcValue
    end
  end

  watchByTagNameMap[watchTagName] = lWatch

  local intervalId = setInterval(function()
    async(function()
      local tag = await(tagApi.read(watchTagName))
      await(checkTag(tag.name, tag.value))
    end):catch(function(err)
      print("motoHours.watch: interval:", err)
    end)
  end, 10000)

  return {
    cancel = function()
      clearInterval(intervalId)
      watchByTagNameMap[watchTagName] = nil
    end,
    getTotalWorkTime = function()
      return lWatch.totalWorkTime or 0
    end
  }
end

return M

Чтобы подключить данный модуль в скрипте требуется оформить вызов:

local motoHours = require("lib.motoHours")

Пример:
Необходимо выводить сообщение с временем наработки тега waterPump в служебных сообщениях сервера каждые 10 секунд.

getWorkTime.lua
local async = require("async")
local motoHours = require("lib.motoHours")

local watch = motoHours.watch({
  watchTagName = "waterPump",
  resetTagName = "resetHours",
})

setInterval(function()
  local t = watch.getTotalWorkTime() / 1000
  print(string.format("Время наработки тега: %d сек", t))
end, 10 * 1000)