[Package development] Working with schedules in Lua will get easier

It will soon get easier to use schedule information specified in a setup’s configuration from within Lua in a package. Previously the schedule was provided to the device as its verbatim configuration value. It looks like this. Expanding this to make a scheduling decision was quite difficult, as the only provided way was by using Python code that replicated what the info-beamer backend was doing. Not ideal.

This will improve: If you specify the "expand_schedules": true value in node.json, info-beamer hosted will soon generate an precalculated schedule that can be easily used within Lua. Here’s how the new __schedules value looks in a generated config.json:

"__schedules": {
    "expanded": [
           [[1728597600, 86400], [1728856800, 86400]]
    ],
    "range": [1728597600, 1209600],
}

Later if a schedule is used in a typical “asset”, “duration”, “schedule” triple forming a typical playlist it might look like this inside the generated config.json:

{
    "asset": { ..full asset info.. },
    "duration": 15,
    "schedule": 0
}

The value in "schedule" can be either "always" or "never" if the schedule is either set to never be active or to always be active. This hasn’t changed. What’s new is the value if there is a schedule set. In the above example the value is 0 which is now an index into the array in __schedules.expanded. There you’ll find all ranges in which the schedule is active. Each value is a tuple consisting of a start time as a unix timestamp as well as an active duration in seconds. In the above examples, two ranges are marked as active. Both having 86400 seconds, so one day, long. The ranges are sorted and never overlap or touch and already honor the timezone setting of the device. This makes it easy to test ranges within Lua, assuming the loaded config is loaded into the config variable:

local function is_schedule_active(schedule)
    if schedule == "always" then
        return true
    elseif schedule == "never" then
        return false
    end
    local now = os.time()
    if now < 10000000 then
        return false -- no valid system time, don't schedule
    end
    for _, range in ipairs(config.__schedules.expanded[schedule+1]) do
        local starts, duration = unpack(range)
        if starts > now then
            break
        elseif now < starts + duration then
            return true
        end
    end
    return false
end

This then be used to decide whether or not an item (or whatever is using schedules) is active:

if is_schedule_active(item.schedule) then
   -- show item on screen
end

The precalculated ranges calculated for normal online devices reach about 14 days into the future. As a device’s config is regenerated every day, this is more than enough. Especially as such a default “online” device refuses to work after 7 days of being offline anyway. For devices with longer offline allowance, the precalculated range is increased accordingly and can be seen in the "range" value within "__schedules".

As an optimization, schedules that aren’t active within the probe range might be set to "never" instead of providing an empty range list. Similarly schedules that are always active within the probed range might return "always" instead a range identical to that in "range".

Once this feature is fully rolled out, most packages that currently don’t have any way of scheduling items will be improved to also handle scheduling, including scheduling included in native playlists.

1 Like

The feature is now enabled. Feedback welcome.