Как мне выполнить глобальную функцию в определенный день в определенное время в Lua?

Я пишу сценарий на Lua, который среди многих других функций будет выполнять один цикл в определенное время в определенный день. Цикл запускается, когда кнопка нажата, размышляя над этим некоторое время, я понял, что мне нужно будет проверить системное время в миллисекундах, используя os.time, которое в табличной форме также может возвращать дату, что очень полезно. Единственное, в чем я застрял, - это как это выразить, и можно ли было бы включить несколько определений os.time; поэтому в день (x) будет выполняться цикл loop1, а в день (y) будет выполняться цикл 2 и так далее. Я, скорее всего, слишком усложняю это ...

Вот мой код: (он вылетает и горит при вызове нажатием кнопки)

function runiftime()

day1 = a;
day2 = b;
day3 = c;
day4 = d;
status = 0; -- Default status == 0
target = day4;


-- Where a, b, c & d are shown above I would like different os.time outputs which relate to days in the future an example output of os.time is => = os.time() outputs '1384988715'.

    repeat

 if os.time() == "day1" then

    os.execute("Some command");
    result = Shell.Execute("Some program", "open", "", "",     SW_SHOWNORMAL, false);
    status = 1;
end

 if os.time() == "day2" then

    os.execute("Some command");
    result = Shell.Execute("Some program", "open", "", "", SW_SHOWNORMAL, false);
    status = 1;
end

 if os.time == "day3" then

    os.execute("Some command");
    result = Shell.Execute("Some program", "open", "", "",     SW_SHOWNORMAL, false);
    status = 1;
end

 if os.time == "day4" then

    os.execute("Some command");
    result = Shell.Execute("Some program", "open", "", "",     SW_SHOWNORMAL, false);
    status = 1;
end


    if status == 1 then
        Input.SetText("feed", "Routine Successful!                                  Waiting for Command...");
    else
        Input.SetText("feed", "Automated Routine Started!           Waiting for OS Clock...");
    end

until (os.time == target);  
end

person Mike Armstrong    schedule 20.11.2013    source источник
comment
Вы говорите, что при вызове он вылетает и горит, но не могли бы вы уточнить? Есть ли конкретное сообщение об ошибке?   -  person Ryan Stein    schedule 21.11.2013
comment
os.time() возвращает число, скорее всего, время unix с эпохи. Сравнивать это со строкой day1 не получается. os.date() может вернуть что-то более подходящее для ваших целей.   -  person greatwolf    schedule 21.11.2013


Ответы (1)


Я заметил несколько проблем с вашим кодом. Прежде всего, половину времени вы сравниваете с os.time, который является функцией, и os.time(), который будет числом. Во-вторых, вы входите в бесконечный цикл с until (os.time == target);, поскольку os.time никогда не изменится, если вы его не измените.

Даже тогда, если вы правильно сравнивали с os.time(), входите в бесконечный цикл, чтобы проверить время, все время будет максимально использовать ЦП для виртуальной машины Lua, поскольку бесконечные циклы обычно используются. Это вероятно остановит процесс, что может быть именно тем, что вы подразумеваете под "сбоем и сгоранием".

И последнее, но не менее важное: сравнение текущего времени со временем в будущем с помощью ==, как правило, является плохой идеей из-за низкой вероятности выполнения условия точно в желаемое время.

Я бы рекомендовал спать как можно дольше, пока самая ранняя задача не будет готова к выполнению. Таким образом, вы избегаете ненужного использования процессорного времени при постоянном опросе. Из Lua вы можете сделать что-то вроде этого.

local target = os.time{year = 2013, month = 11, day = 21, hour = 9, min = 30}

local function sleep(s) -- wait for `s` seconds
    if type(s) ~= 'number' then
        error's is not a number'
    elseif s < 1 then
      return
    end
    s = math.floor(s)

    -- Windows (delay range limited to 0-9999)
    --os.execute('choice /n /d:y /t:' .. math.min(s, 9999) .. ' > NUL')

    -- *nix
    os.execute('sleep ' .. s)
end

local d
repeat
    d = target - os.time()
    if d <= 0 then break end
    sleep(d) -- sleep for the difference
until false

print'Target time has arrived.'

В идеале вы могли бы добиться чего-то подобного, настроив планировщик вашей операционной системы, например cron на * nix или Task Scheduler в Windows контролируют время выполнения скрипта. Однако, если вы планируете управлять временем через Lua, просмотрите эту страницу в Программирование на Lua.


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

local alarm = {}
local function sort_alarm(a, b) return a.time > b.time end
local function schedule(when, what)
    if os.time() <= when then
        table.insert(alarm, {time = when, event = what})
        table.sort(alarm, sort_alarm)
    else -- What to do when a scheduled event is in the past?
        what()
    end
end
local function run_scheduler()
    local d
    while #alarm > 0 do
        d = alarm[#alarm].time - os.time()
        if d <= 0 then
            -- Pop the latest alarm from the stack and call it.
            table.remove(alarm).event()
        else
            sleep(d)
        end
    end
end

-- Schedule some events.
schedule(os.time{year = 2013, month = 11, day = 22, hour = 9}, function()
    print'This function runs at a specific point in time.'
end)

schedule(os.time() + 30, function()
    print'This function will run 30 seconds from the start of the script.'
end)

schedule(os.time() + 5, function()
    print'This function will run 5 seconds from the start of the script.'
    schedule(os.time() + 10, function()
        print'You can even schedule new functions this way.'
        print'This one will run 15 seconds from the start of the script.'
    end)
end)

local function repeater()
    print'How about a repeating event?'
    print'This function will run every 10 seconds.'
    schedule(os.time() + 10, repeater)
end
schedule(os.time() + 10, repeater)

-- Start the scheduler loop.
run_scheduler()

-- No more events left at this point, thus the script will end.

В заключение я должен отметить, что если вы планируете серьезно использовать это, вы захотите заменить функцию sleep чем-то более надежным в будущем. В пользовательской вики есть страница, на которой перечислены некоторые решения. Я бы сказал, что это проще всего сделать из LuaJIT, используя FFI, если вы уже используете его. .

person Ryan Stein    schedule 21.11.2013
comment
Спасибо! Большое спасибо за вашу помощь @RyanStein, это выглядит значительно лучше и эффективнее, чем моя попытка. Мой следующий вопрос: можно ли иметь несколько целевых переменных? например, как мне изменить этот код, чтобы можно было проверять более одного раза с установленным механизмом сна? - person Mike Armstrong; 21.11.2013
comment
@MikeArmstrong Я отредактировал свой ответ примером того, как можно создать планировщик задач на Lua. Пожалуйста, дайте мне знать, что вы думаете. - person Ryan Stein; 21.11.2013
comment
@RyanStein table.remove(alarm).event() опечатка? - person ms2008; 22.11.2013
comment
@ ms2008vip Что ты видишь в этом не так? table.remove возвращает удаленный элемент из таблицы alarm при который называется event(). - person Ryan Stein; 22.11.2013
comment
@RyanStein Удаляет ли сначала? А затем вызвать событие ()? Извините, я просто не понял синтаксис. - person ms2008; 22.11.2013
comment
@ ms2008vip Правильно. Элемент удаляется из таблицы, возвращается, затем для возвращенного элемента вызывается event(). Это несколько похоже на цепочку методов. - person Ryan Stein; 22.11.2013