Skip to content

pebblebed-tech/schedule

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESPHome Schedule Component

A comprehensive scheduling component for ESPHome that integrates seamlessly with Home Assistant schedules. Control switches, buttons, and other devices based on time-based schedules with support for schedule variables (temperature, position, etc.) and multiple operating modes.

When paired with a RTC such as DS1307, this allows the device to operate independently from Home Assistant.

Overview

The Schedule component provides two platform types for different scheduling needs:

Platform Types

  • Switch Platform - State-based scheduling for devices that need ON/OFF control over time periods (heating, lights, pumps)
  • Button Platform - Event-based scheduling for momentary actions at specific times (blinds, feeders, notifications)

Common Features

Both platforms share these core capabilities:

  • Home Assistant Integration - Automatic sync with HA schedule helpers
  • Persistent Storage - Schedules saved to NVS flash, survive reboots
  • Schedule Variables - User-defined additional data (temperature, position) defined in Home Assistant schedule entries
  • Multiple Modes - Manual and automatic operation modes
  • Smart Mode Handling - All modes always visible, automatic validation and correction
  • Error Notifications - Automatic HA notifications for invalid mode selections
  • Offline Operation - Works with RTC when WiFi/HA unavailable

Common Elements

Time Source Configuration

Both platforms require a time source. An RTC is recommended for offline operation:

time:
  - platform: ds1307  # Or DS3231
    id: rtc_time
    update_interval: never
  - platform: homeassistant
    on_time_sync:
      then:
        ds1307.write_time:

Home Assistant API

API connection required for schedule synchronization:

api:
  encryption: 
    key: !secret api_key
  homeassistant_services: true

Schedule Update Button

Both platforms include an update button to manually refresh the schedule from Home Assistant:

schedule_update_button:
  name: "Update Schedule"

Mode Selector

Both platforms include a mode selector for manual override:

  • Switch: 5 modes (Manual Off, Early Off, Auto, Manual On, Boost On)
  • Button: 2 modes (Disabled, Enabled)
mode_selector:
  name: "Schedule Mode"

Schedule Variables (Data Sensors)

Both platforms support additional data attached to schedule entries, defined in Home Assistant and exposed as sensors in ESPHome:

scheduled_data_items:
  - id: temp_sensor
    label: "temp"
    item_type: float
    name: "Target Temperature"

In Home Assistant, attach data to schedule entries:

{
  "temp": 21.5
}

Text Sensors

Both platforms provide informational text sensors:

current_event:
  name: "Current Event"  # Shows current schedule state/event
next_event:
  name: "Next Event"     # Shows next upcoming event

Requirements

Hardware Requirements

  • ESP32 or derivatives - Tested on ESP32-S3. Storage requires NVS (ESP8266 not supported)
  • Real-Time Clock (RTC) Module - Required for offline operation
    • Supported: DS3231, DS1307, or compatible I2C RTC
    • Maintains timekeeping during WiFi/HA outages

Software Requirements

  • ESPHome 2025.11.1 or later
  • Home Assistant 2025.11.3 or later with schedule helper integration
  • API connection to Home Assistant (for schedule sync)

Test Hardware

Platform Documentation

Choose your platform based on your use case:

  • Switch Platform - For state-based scheduling (ON/OFF over time periods)
  • Button Platform - For event-based scheduling (momentary actions at specific times)

Quick Start Examples

Switch Platform Example

switch:
  - platform: schedule
    id: heating_schedule
    name: "Heating"
    ha_schedule_entity_id: "schedule.heating"
    
    schedule_update_button:
      name: "Update Heating Schedule"
    
    mode_selector:
      name: "Heating Mode"
      
    on_turn_on:
      - logger.log: "Switch Turned ON by schedule"
    on_turn_off:
      - logger.log: "Switch Turned OFF by schedule" 

Button Platform Example

button:
  - platform: schedule
    id: feeder_schedule
    name: "Feed Cat"
    ha_schedule_entity_id: "schedule.cat_feeding"
    
    schedule_update_button:
      name: "Update Feeding Schedule"
    
    mode_selector:
      name: "Feeding Schedule Mode"
      
    on_press:
      - logger.log: "Feeding time!"

Examples

Complete, ready-to-use YAML configuration examples are available in the examples/ folder:

For code snippets and detailed explanations, see Configuration Examples

Technical Documentation

For detailed technical information about component architecture, state machines, and internal workings:

Storage Efficiency

NVS (Non-Volatile Storage) Usage

The schedule component uses ESP32's NVS flash memory to persistently store schedules. The max_schedule_size setting pre-allocates NVS space for your schedules.

⚠️ Important NVS Considerations:

  • Over-provisioning Warning: Setting max_schedule_size too high permanently reserves NVS space
  • NVS is Limited: ESP32 NVS partition is typically 12-20KB
  • Right-sizing: Set max_schedule_size to actual needs + small buffer (e.g., if you use 15 entries, set to 21, not 100)
  • Factory Reset Recovery: Reduce max_schedule_size and factory reset to reclaim over-provisioned space

Platform Storage Comparison

State-Based (Switch):

  • Stores ON/OFF time pairs
  • Storage: (entries × 4) + 4 bytes
  • Example: 21 entries = 88 bytes

Event-Based (Button):

  • Stores event times only
  • Storage: (entries × 2) + 4 bytes (50% savings!)
  • Example: 21 entries = 46 bytes

Home Assistant Schedule Configuration

Create schedule helpers in Home Assistant:

Configuration → Helpers → Add Helper → Schedule

Open Home Assistant

Add time slots for each day of the week. For schedule variables, see platform-specific documentation.


  • current_event (Optional, text_sensor config): Shows current schedule entry index
    • name (string): Sensor display name
    • Auto-generates ID: {switch_id}_current_event_sensor
  • next_event (Optional, text_sensor config): Shows next schedule entry index
    • name (string): Sensor display name
    • Auto-generates ID: {switch_id}_next_event_sensor
  • scheduled_data_items (Optional, list): Custom data fields for schedule entries
  • All other options from Switch Component are also available (e.g., icon, entity_category, disabled_by_default, on_turn_on, on_turn_off, etc.).

Schedule Data Items

Add custom data to each schedule entry (temperature, brightness, etc.):

scheduled_data_items:
  - id: target_temp
    label: "temperature"
    item_type: float
    off_behavior: OFF_VALUE
    off_value: 15.0
    manual_behavior: MANUAL_VALUE
    manual_value: 20.0

Data Item Configuration

  • id (Optional, ID): Component identifier. Auto-generated if not specified. Must be explicitly provided if you need to access the sensor value in lambdas or C++ code (e.g., using SCHEDULE_GET_DATA macro).

  • label (Required, string): Field name in Home Assistant schedule data

  • item_type (Required, enum): Data type

    • uint8_t - 0 to 255 (1 byte)
    • uint16_t - 0 to 65,535 (2 bytes)
    • int32_t - -2,147,483,648 to 2,147,483,647 (4 bytes)
    • float - Floating point number (4 bytes)

    Note: To minimize NVS storage usage, choose the smallest data type that accommodates your values. For example, use uint8_t for percentages (0-100) or temperatures in a limited range, rather than float or int32_t. But the data item state returned will always be a float.

  • off_behavior (Optional, enum): Behavior when schedule is OFF. Default: NAN

    • NAN - Sensor shows NaN
    • LAST_ON_VALUE - Keep last ON value
    • OFF_VALUE - Use specific off_value
  • off_value (Optional, number): Value to use when off_behavior is OFF_VALUE

  • manual_behavior (Optional, enum): Behavior in manual mode. Default: NAN

    • NAN - Sensor shows NaN
    • LAST_ON_VALUE - Keep last ON value
    • MANUAL_VALUE - Use specific manual_value
  • manual_value (Optional, number): Value to use when manual_behavior is MANUAL_VALUE

Operating Modes

The switch platform supports 5 operating modes via the mode selector:

Mode Behavior
Manual Off Force switch OFF, ignore schedule completely
Early Off Turn OFF immediately, return to Auto at next schedule event
Auto Follow schedule automatically (default)
Manual On Force switch ON, ignore schedule completely
Boost On Turn ON immediately, return to Auto at next ON event

Mode Availability:

  • All 5 modes are always visible in Home Assistant (no integration reload required)
  • Schedule-dependent modes (Auto, Early Off, Boost On) require a populated schedule
  • If you select a schedule-dependent mode when the schedule is empty:
    • A Home Assistant notification is sent explaining the issue
    • The mode automatically reverts to Manual Off after 2 seconds
  • If the schedule becomes empty while in a schedule-dependent mode:
    • A notification is sent and the mode reverts to Manual Off
  • Manual modes (Manual Off, Manual On) work regardless of schedule state

Lambda Methods

Access schedule components in lambda expressions:

// Check if schedule is currently ON
if (id(heating_schedule).state) {
  // Schedule is ON
}

// Get current mode
auto mode = id(heating_schedule_mode_select).state;

// Get data sensor value using SCHEDULE_GET_DATA macro
float temp = SCHEDULE_GET_DATA(heating_schedule, "temperature");

// Check if valid value
if (!isnan(temp)) {
  // Use temp value
}

// Change mode programmatically
auto call = id(heating_schedule_mode_select).make_call();
call.set_option("Auto");
call.perform();

// Trigger schedule update
id(heating_schedule_update_button).request_schedule();

SCHEDULE_GET_DATA Macro

The SCHEDULE_GET_DATA macro provides a convenient way to retrieve data sensor values from a schedule component. It handles null pointer checking and logging automatically.

Important: If you need to access data sensor values in lambdas or other code, you must specify an id for each datasensor in your configuration.

Usage:

float value = SCHEDULE_GET_DATA(schedule_id, "label");

Parameters:

  • schedule_id - The ID of your schedule component (without id() wrapper)
  • label - The label string defined in scheduled_data_items configuration

Returns:

  • The current sensor value as a float
  • NaN if the sensor is not found or hasn't been populated

Example:

// In your YAML configuration:
// scheduled_data_items:
//   - id: heating_temp      # ID is REQUIRED to access the value
//     label: "temperature"
//     item_type: float

// In lambda code:
float temp = SCHEDULE_GET_DATA(heating_schedule, "temperature");

if (!isnan(temp)) {
  ESP_LOGI("heating", "Target temperature: %.1f�C", temp);
  id(thermostat).target_temperature = temp;
} else {
  ESP_LOGW("heating", "No temperature data available");
}

Equivalent Long-Form Code:

// Instead of:
float temp = SCHEDULE_GET_DATA(heating_schedule, "temperature");

// You can write:
float temp = NAN;
auto *sensor = id(heating_schedule).get_data_sensor("temperature");
if (sensor != nullptr) {
  temp = sensor->state;
} else {
  ESP_LOGW("schedule", "Data sensor with label 'temperature' not found in schedule 'heating_schedule'");
}

Advantages of Using the Macro:

  • Less boilerplate code
  • Automatic null pointer safety
  • Consistent error logging
  • Cleaner, more readable lambdas
  • Reduces copy-paste errors

Configuration Examples

For detailed configuration examples including:

  • Basic heating control
  • Thermostat with temperature control
  • Multi-zone heating systems

See Switch Platform Examples


Home Assistant Schedules

The Schedule component syncs with Home Assistant schedule helpers. This section explains how to create and configure HA schedules with additional data fields.

Creating a Schedule Helper

Via Home Assistant UI

  1. Configuration → Helpers → Add Helper → Schedule
  2. Enter details:
    • Name: Heating (creates entity schedule.heating)
    • Icon: mdi:radiator
  3. Click Create

Via configuration.yaml

schedule:
  heating:
    name: Heating
    icon: mdi:radiator
    monday:
      - from: "06:00:00"
        to: "08:00:00"
      - from: "17:00:00"
        to: "22:00:00"
    tuesday:
      - from: "06:00:00"
        to: "08:00:00"
      - from: "17:00:00"
        to: "22:00:00"
    # ... continue for other days

Adding Schedule Entries

Each schedule entry has:

  • from: Start time (HH:MM:SS)
  • to: End time (HH:MM:SS) - Only for state-based
  • data: Custom data fields (optional)

State-Based Schedule (Switch)

schedule:
  heating:
    name: Heating Schedule
    monday:
      - from: "06:00:00"
        to: "08:00:00"
        data:
          temperature: 21.0
      - from: "17:00:00"
        to: "22:00:00"
        data:
          temperature: 20.5
    tuesday:
      - from: "06:00:00"
        to: "08:00:00"
        data:
          temperature: 21.0
      - from: "17:00:00"
        to: "22:00:00"
        data:
          temperature: 20.5
    # ... continue for remaining days

Event-Based Schedule (Button)

schedule:
  blinds:
    name: Blinds Schedule
    monday:
      - from: "07:00:00"
        to: "07:00:01"
        data:
          position: 100.0
      - from: "20:00:00"
        to: "20:00:01"
        data:
          position: 0.0
    tuesday:
      - from: "07:00:00"
        to: "07:00:01"
        data:
          position: 100.0
      - from: "20:00:00"
        to: "20:00:01"
        data:
          position: 0.0
    # ... continue for remaining days

Note: Event-based schedules require both from and to fields in Home Assistant, but only the from time triggers the event. Use to as from + 1 second.

Additional Data Fields

Additional data fields allow you to store custom values with each schedule entry. These are accessed via data sensors in ESPHome.

Important: Data sensor IDs are auto-generated if not specified. However, if you need to access the sensor values in lambdas or other code (e.g., using SCHEDULE_GET_DATA), you must explicitly provide an id for each data sensor.

Data Field Types

Home Assistant supports:

  • Numbers: Integer or float values
  • Strings: Text values (not currently supported by ESPHome component)
  • Booleans: true/false (not currently supported by ESPHome component)

Matching Data Fields

The label in ESPHome MUST match the field name in HA schedule data:

ESPHome:

scheduled_data_items:
  - id: heating_temp
    label: "temperature"  # This must match HA
    item_type: float

Home Assistant:

schedule:
  heating:
    monday:
      - from: "06:00:00"
        to: "08:00:00"
        data:
          temperature: 21.0  # Field name matches "temperature"

Multiple Data Fields

You can have multiple data fields per entry:

ESPHome:

scheduled_data_items:
  - id: target_temp
    label: "temperature"
    item_type: float
  - id: target_humidity
    label: "humidity"
    item_type: uint8_t
  - id: fan_speed
    label: "fan_speed"
    item_type: uint8_t

Home Assistant:

schedule:
  climate_control:
    monday:
      - from: "06:00:00"
        to: "22:00:00"
        data:
          temperature: 21.5
          humidity: 50
          fan_speed: 2

Data Sensor Behavior

Data sensors show different values depending on schedule state and configuration:

State-Based (Switch)

Schedule State Mode Data Sensor Value
ON Auto Current schedule data value
OFF Auto Depends on off_behavior
- Manual Off/On Depends on manual_behavior

off_behavior Options:

  • NAN - Sensor shows NaN
  • LAST_ON_VALUE - Keeps last ON value
  • OFF_VALUE - Shows configured off_value

manual_behavior Options:

  • NAN - Sensor shows NaN
  • LAST_ON_VALUE - Keeps last ON value
  • MANUAL_VALUE - Shows configured manual_value

Event-Based (Button)

Data sensors always show the value from the next scheduled event. If no upcoming event has data, sensor shows NaN.

Complete Example

Home Assistant schedule helper:

schedule:
  multi_zone_heating:
    name: Multi-Zone Heating
    icon: mdi:radiator
    monday:
      - from: "06:00:00"
        to: "08:00:00"
        data:
          living_room_temp: 21.0
          bedroom_temp: 18.0
          bathroom_temp: 22.0
      - from: "17:00:00"
        to: "22:00:00"
        data:
          living_room_temp: 20.5
          bedroom_temp: 19.0
          bathroom_temp: 21.0
    tuesday:
      - from: "06:00:00"
        to: "08:00:00"
        data:
          living_room_temp: 21.0
          bedroom_temp: 18.0
          bathroom_temp: 22.0
      - from: "17:00:00"
        to: "22:00:00"
        data:
          living_room_temp: 20.5
          bedroom_temp: 19.0
          bathroom_temp: 21.0
    # ... continue for remaining days

ESPHome configuration:

switch:
  - platform: schedule
    id: heating_schedule
    name: "Heating Schedule"
    ha_schedule_entity_id: "schedule.multi_zone_heating"
    
    schedule_update_button:
      name: "Update Heating Schedule"
    
    mode_selector:
      name: "Heating Mode"
    
    scheduled_data_items:
      - id: living_room_target
        label: "living_room_temp"
        item_type: float
        off_behavior: OFF_VALUE
        off_value: 15.0
        
      - id: bedroom_target
        label: "bedroom_temp"
        item_type: float
        off_behavior: OFF_VALUE
        off_value: 15.0
        
      - id: bathroom_target
        label: "bathroom_temp"
        item_type: float
        off_behavior: OFF_VALUE
        off_value: 16.0

sensor:
  - platform: template
    name: "Living Room Target"
    lambda: 'return id(living_room_target).state;'
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    
  - platform: template
    name: "Bedroom Target"
    lambda: 'return id(bedroom_target).state;'
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    
  - platform: template
    name: "Bathroom Target"
    lambda: 'return id(bathroom_target).state;'
    unit_of_measurement: "°C"
    accuracy_decimals: 1

Troubleshooting

Schedule Not Syncing

Symptoms: ESPHome doesn't receive schedule updates

Checks:

  1. Verify ha_schedule_entity_id matches exactly
  2. Check ESPHome logs for API errors
  3. Ensure Home Assistant API connection is working
  4. Press the update button manually to force sync

Data Fields Showing NaN

Symptoms: Data sensors always show NaN

Checks:

  1. Verify label in ESPHome matches field name in HA exactly
  2. Check off_behavior and manual_behavior settings
  3. Ensure schedule entries actually have the data field
  4. Check ESPHome logs for parsing errors

Wrong Data Type

Symptoms: Error notification about incorrect data type

Checks:

  1. Verify item_type matches data type in HA
  2. Use float for decimal numbers
  3. Use int32_t for whole numbers (positive or negative)
  4. Use uint8_t or uint16_t for small positive integers

Schedule Entry Limit

Symptoms: Error notification about oversized schedule

Solution:

  • Reduce number of schedule entries in HA
  • Increase max_schedule_size in ESPHome (default: 21)
  • Consider splitting into multiple schedules

Best Practices

  1. Consistent Naming: Use clear, descriptive names for schedules and data fields
  2. Field Name Matching: Always ensure ESPHome label matches HA field name exactly
  3. Data Types: Use appropriate data types to save storage
  4. Entry Limits: Keep entries under limit (default 21) or adjust max_schedule_size
  5. Manual Updates: Press update button after modifying HA schedule
  6. Validation: Check ESPHome logs and HA notifications for errors

Advanced Topics

Storage Efficiency

Choose the right platform for storage efficiency:

State-Based (Switch):

  • Each entry: 4 bytes (2 bytes ON time + 2 bytes OFF time)
  • Overhead: 4 bytes (entry count + terminator)
  • Example: 21 entries = (21 × 4) + 4 = 88 bytes

Event-Based (Button):

  • Each entry: 2 bytes (event time only)
  • Overhead: 4 bytes (entry count + terminator)
  • Example: 21 entries = (21 × 2) + 4 = 46 bytes (47% savings!)

NVS Space Management:

The max_schedule_size setting pre-allocates NVS space. To calculate total NVS usage:

State-Based: (max_schedule_size × 4) + 4 bytes per schedule
Event-Based: (max_schedule_size × 2) + 4 bytes per schedule

Example - Multiple Schedules:

  • 3 switches with max_schedule_size=21: 3 × 88 = 264 bytes
  • 2 buttons with max_schedule_size=21: 2 × 46 = 92 bytes
  • Total NVS: 356 bytes

⚠️ Best Practice: Only allocate what you need. Setting max_schedule_size=100 "just in case" wastes valuable NVS space. If you later need to reduce it, a factory reset will be required to reclaim the space.

Performance Characteristics

  • Setup Time: ~100-200ms per component
  • Loop Cycle: ~20ms (state machine check)
  • NVS Writes: Only on schedule updates (not on every state change)
  • Memory Usage: ~200 bytes + schedule data + data sensors

Error Notifications

The component automatically sends Home Assistant persistent notifications for:

  1. Schedule Retrieval Failure - HA entity not found
  2. Parsing Errors - Invalid JSON or structure
  3. Missing Fields - Required data missing
  4. Invalid Values - Out of range or wrong type
  5. Oversized Schedule - Too many entries
  6. Data Sensor Errors - Missing or incorrect data type

Notifications include:

  • ESPHome device name
  • Schedule entity ID
  • Specific error details
  • Timestamp

Backup and Restore

Schedules are stored in ESP32 NVS (Non-Volatile Storage) flash and persist across:

  • Reboots
  • Power cycles
  • Firmware updates (if NVS partition preserved)

To backup:

  • Schedules sync from Home Assistant (no manual backup needed)

To restore:

  • Press update button after restoring HA
  • Or wait for automatic sync on next update

Factory Reset (NVS Recovery):

If you've over-provisioned max_schedule_size during development, you can reclaim NVS space:

  1. Reduce max_schedule_size in your YAML to actual needs
  2. Perform a factory reset (clears all NVS data)
  3. Recompile and upload firmware
  4. Re-download schedules from Home Assistant

This is useful when transitioning from development (with large safety margins) to production (optimized storage).


Support and Resources

  • Ready-to-Use Examples: examples/ folder - Complete YAML configurations
  • Full Documentation: docs/ folder
  • Configuration Examples: docs/EXAMPLES.md - Code snippets and explanations
  • Architecture Details: docs/ARCHITECTURE.md
  • Developer Guide: docs/ADDING_NEW_PLATFORMS.md
  • Quick Reference: docs/QUICK_REFERENCE.md

Component Version: 1.0.0
ESPHome Version: 2024.6.0+
Home Assistant Version: 2024.6.0+


Repository: pebblebed-tech/schedule

About

ESPHome Scheduling component

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published