New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@xiboplayer/schedule

Package Overview
Dependencies
Maintainers
1
Versions
81
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xiboplayer/schedule

Complete scheduling solution: campaigns, dayparting, interrupts, and overlays

latest
Source
npmnpm
Version
0.7.23
Version published
Maintainers
1
Created
Source

@xiboplayer/schedule

Complete scheduling solution: campaigns, dayparting, interrupts, overlays, and timeline prediction.

Overview

Manages all aspects of digital signage scheduling to determine which layouts play when:

  • Campaign scheduling -- groups of layouts with time windows and priorities
  • Dayparting -- weekly time slots (Mon-Fri 09:00-17:00, evenings, weekends) with midnight-crossing support
  • Priority fallback -- higher-priority layouts hide lower-priority ones; rate limiting triggers automatic fallback
  • Rate limiting -- maxPlaysPerHour with even distribution (prevents bursts, ensures spacing)
  • Interrupts (Share of Voice) -- layouts that must play X% of each hour, interleaved with normal content
  • Overlays -- layouts that appear on top of main layouts without interrupting playback
  • Criteria evaluation -- conditional display based on time, weather, custom display properties
  • Geo-fencing -- location-based filtering (point + radius, Haversine distance)
  • Timeline prediction -- deterministic simulation of future playback for UI overlays
  • Default layout -- fallback when no campaigns are active

Architecture

CMS Schedule XML
        |
        v
+-------------------------------------+
|  Schedule Parser                    |
|  +- campaigns[]                     |
|  +- layouts[]                       |
|  +- overlays[]                      |
|  +- default layout                  |
+-------------------------------------+
        |
        v
+-------------------------------------+
|  Evaluation Engine                  |
|  +- Recurrence (Week/Day/Month)     |
|  +- Time windows (dayparting)       |
|  +- Criteria (weather, properties)  |
|  +- Geo-fencing                     |
|  +- Priority + rate-limit filtering |
+-------------------------------------+
        |
        v
+-------------------------------------+
|  Schedule Queue Builder (LCM-based) |
|  Deterministic round-robin with:    |
|  +- Rate-limited slots (even spaced)|
|  +- Priority fallback               |
|  +- Default fills gaps              |
+-------------------------------------+
        |
        +-> getCurrentLayouts()        -> Renderer
        +-> getLayoutsInTimeRange()    -> Timeline Overlay
        +-> Track play history         -> Rate limiting

Installation

npm install @xiboplayer/schedule

Usage

Basic scheduling

import { ScheduleManager } from '@xiboplayer/schedule';

const schedule = new ScheduleManager();

schedule.setSchedule({
  campaigns: [
    {
      id: 1,
      priority: 100,
      fromdt: '2025-01-01 09:00',
      todt: '2025-12-31 17:00',
      recurrenceType: 'Week',
      recurrenceRepeatsOn: '1,2,3,4,5', // Mon-Fri
      layouts: [
        { id: 10, file: '10.xlf', duration: 30 },
        { id: 11, file: '11.xlf', duration: 30 },
      ],
    },
  ],
  default: '99.xlf',
});

const layoutsToPlay = schedule.getCurrentLayouts();
// Business hours: ['10.xlf', '11.xlf']
// After hours: ['99.xlf'] (default)

Dayparting with midnight crossing

schedule.setSchedule({
  layouts: [
    {
      id: 1,
      file: '1.xlf',
      recurrenceType: 'Week',
      recurrenceRepeatsOn: '1,2,3,4,5,6,7',
      fromdt: '1970-01-01 22:00:00', // 10 PM
      todt: '1970-01-01 02:00:00',   // 2 AM (next day)
    },
  ],
});

// Friday 23:00: returns ['1.xlf']
// Saturday 01:00: returns ['1.xlf'] (midnight crossing works)

Rate limiting with even distribution

schedule.setSchedule({
  layouts: [
    {
      id: 1,
      file: '1.xlf',
      maxPlaysPerHour: 3, // 3 times per hour, evenly spaced
    },
  ],
});

schedule.recordPlay('1'); // Play at 09:00
// Can't play again until 09:20 (60 / 3 = 20 min minimum gap)

Interrupts (Share of Voice)

schedule.setSchedule({
  layouts: [
    { id: 1, file: '1.xlf', duration: 30 },
    { id: 2, file: '2.xlf', duration: 30, shareOfVoice: 20 }, // 20% of each hour
  ],
});

const layouts = schedule.getCurrentLayouts();
// Interleaved: normal, normal, interrupt, normal, normal, interrupt, ...

Criteria-based display

schedule.setSchedule({
  layouts: [
    {
      id: 1,
      file: '1.xlf',
      criteria: [
        { metric: 'weatherTemp', condition: 'greaterThan', value: '25', type: 'number' },
      ],
    },
  ],
});

schedule.setWeatherData({ temperature: 28, humidity: 65 });
// Layout 1 displays only when temperature > 25

Geo-fencing

schedule.setLocation(37.7749, -122.4194);

schedule.setSchedule({
  layouts: [
    {
      id: 1,
      file: '1.xlf',
      isGeoAware: true,
      geoLocation: '37.7749,-122.4194,500', // lat,lng,radius_meters
    },
  ],
});

// Returns ['1.xlf'] only if player is within 500m

Timeline prediction

const timeline = calculateTimeline(queue, queuePosition, {
  from: new Date(),
  hours: 2,
  defaultLayout: schedule.schedule.default,
  durations: durations,
});

// Returns:
// [
//   { layoutFile: '10.xlf', startTime, endTime, duration: 30, isDefault: false },
//   { layoutFile: '11.xlf', startTime, endTime, duration: 30, isDefault: false },
//   ...
// ]

Campaign Evaluation Algorithm

When getCurrentLayouts() is called:

  • Filter time-active items -- campaigns and standalone layouts within their date/time window and recurrence rules
  • Apply criteria -- filter by weather, display properties, geo-fencing
  • Apply rate limiting -- exclude layouts that exceeded maxPlaysPerHour
  • Find max priority -- only max priority items win
  • Extract layouts -- campaigns return all their layouts; standalone layouts contribute themselves
  • Process interrupts -- separate interrupt layouts, calculate share-of-voice, interleave
  • Return layout files -- ready for the renderer

Key Concepts

Schedule Queue (LCM-based)

The queue is a pre-computed, deterministic round-robin cycle:

  • LCM period -- Least Common Multiple of all maxPlaysPerHour intervals (capped at 2 hours)
  • Simulation -- walks the period applying priority and rate-limit rules at each step
  • Caching -- reused until the active layout set changes
  • Predictable -- answers "what's playing in 30 minutes?" offline

Dayparting

TypePatternExample
WeekSpecific days + time-of-dayMon-Fri 09:00-17:00
DayDaily with optional intervalEvery 2 days
MonthSpecific days of month1st, 15th (monthly)

Midnight crossing: 22:00 - 02:00 works across day boundaries.

Criteria Evaluation

Built-in metrics: dayOfWeek, dayOfMonth, month, hour, isoDay

Weather metrics: weatherTemp, weatherHumidity, weatherWindSpeed, weatherCondition, weatherCloudCover

Operators: equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals, contains, startsWith, endsWith, in

Geo-fencing

  • Format: "lat,lng,radius" (e.g., "37.7749,-122.4194,500")
  • Default radius: 500 meters
  • Calculation: Haversine formula (great-circle distance)
  • Permissive: if no location available, layout displays (fail-open for offline)

API Reference

Constructor

new ScheduleManager(options?)
OptionTypeDescription
interruptSchedulerInterruptScheduler?Optional interrupt handler
displayPropertiesObject?Custom display fields from CMS

Methods

MethodReturnsDescription
setSchedule(schedule)voidLoad schedule from XMDS response
getCurrentLayouts()string[]Layouts active now
getLayoutsAtTime(date)string[]Layouts at specific time
getAllLayoutsAtTime(date)ArrayAll time-active layouts with metadata
getScheduleQueue(durations){queue, periodSeconds}Pre-computed round-robin queue
popNextFromQueue(durations){layoutId, duration}Pop next entry, advance position
peekNextInQueue(durations){layoutId, duration}Peek without advancing
recordPlay(layoutId)voidTrack a play for rate limiting
canPlayLayout(layoutId, max)booleanCheck if layout can play now
setWeatherData(data)voidUpdate weather for criteria
setLocation(lat, lng)voidSet GPS location for geo-fencing
setDisplayProperties(props)voidSet custom display fields
detectConflicts(options)ArrayFind priority-shadowing conflicts

Overlay Methods

MethodReturnsDescription
setOverlays(overlays)voidUpdate overlay list
getCurrentOverlays()ArrayActive overlays (sorted by priority)
shouldCheckOverlays(lastCheck)booleanCheck interval (every 60s)

Timeline Functions

import { calculateTimeline, parseLayoutDuration, buildScheduleQueue } from '@xiboplayer/schedule';

const { duration } = parseLayoutDuration(xlfXml, videoDurations?);
const { queue, periodSeconds } = buildScheduleQueue(allLayouts, durations);
const timeline = calculateTimeline(queue, position, { from, hours, defaultLayout, durations });

Dependencies

No external dependencies -- fully self-contained scheduling engine.

  • @xiboplayer/utils -- logging only

xiboplayer.org · Part of the XiboPlayer SDK

Keywords

xibo

FAQs

Package last updated on 16 Apr 2026

Related posts