Files
PlantWater/SCHEDULER_README.md
2025-07-20 11:52:00 -06:00

9.9 KiB

Scheduler Module

The scheduler module provides flexible time-based automation for the plant watering system, with NVS persistence and full MQTT control.

Features

  • Multiple Schedule Types:
    • Interval-based (every X minutes)
    • Time of day (daily at specific time)
    • Day-specific (specific days at specific time)
  • Per-Pump Scheduling: Up to 4 independent schedules per pump
  • NTP Time Synchronization: Automatic internet time sync
  • Holiday Mode: Pause all schedules without deleting them
  • MQTT Configuration: Full remote control and monitoring
  • NVS Persistence: Schedules survive power cycles
  • Manual Override: Test schedules without waiting
  • No External Dependencies: Built-in JSON handling

Schedule Configuration

Schedule Types

1. Interval Schedule

Waters every X minutes from the last run time.

{
  "type": "interval",
  "enabled": true,
  "interval_minutes": 120,
  "duration_ms": 15000,
  "speed_percent": 70
}

2. Time of Day Schedule

Waters daily at a specific time.

{
  "type": "time_of_day",
  "enabled": true,
  "hour": 6,
  "minute": 30,
  "duration_ms": 20000,
  "speed_percent": 80
}

3. Days and Time Schedule

Waters on specific days at a specific time.

{
  "type": "days_time",
  "enabled": true,
  "hour": 18,
  "minute": 0,
  "days_mask": 42,
  "duration_ms": 25000,
  "speed_percent": 75
}

Days Mask Values

  • Sunday: 1 (bit 0)
  • Monday: 2 (bit 1)
  • Tuesday: 4 (bit 2)
  • Wednesday: 8 (bit 3)
  • Thursday: 16 (bit 4)
  • Friday: 32 (bit 5)
  • Saturday: 64 (bit 6)

Common masks:

  • Daily: 127 (all days)
  • Weekdays: 62 (Mon-Fri)
  • Weekends: 65 (Sat-Sun)
  • Mon/Wed/Fri: 42

MQTT Topics

Schedule Configuration

Configure individual schedules for each pump.

Topic: plant_watering/schedule/[pump_id]/[schedule_id]/config

  • pump_id: 1 or 2
  • schedule_id: 0-3

Example: Configure pump 1, schedule 0 for daily 6:30 AM watering

mosquitto_pub -h <broker> -t "plant_watering/schedule/1/0/config" -m '{
  "type": "time_of_day",
  "enabled": true,
  "hour": 6,
  "minute": 30,
  "duration_ms": 20000,
  "speed_percent": 80
}'

View All Schedules

Get all configured schedules on demand.

Topic: plant_watering/commands/get_schedules Payload: Any value (e.g., "1")

# Request all schedules
mosquitto_pub -h <broker> -t "plant_watering/commands/get_schedules" -m "1"

# Monitor the responses
mosquitto_sub -h <broker> -t "plant_watering/schedule/+/+/current" -t "plant_watering/schedule/summary" -v

Response Topics:

  • plant_watering/schedule/[pump_id]/[schedule_id]/current - Each configured schedule
  • plant_watering/schedule/summary - Summary of all schedules

Summary format:

{
  "total_schedules": 4,
  "active_schedules": 3,
  "holiday_mode": false,
  "time_sync": true
}

View Pump Schedules

Get schedules for a specific pump.

Topic: plant_watering/schedule/[pump_id]/get Payload: Any value

# Get all schedules for pump 1
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/get" -m "1"

# Get all schedules for pump 2  
mosquitto_pub -h <broker> -t "plant_watering/schedule/2/get" -m "1"

Schedule Status

The system publishes schedule status after configuration and periodically.

Topic: plant_watering/schedule/[pump_id]/[schedule_id]/status

Response:

{
  "pump_id": 1,
  "schedule_id": 0,
  "type": "time_of_day",
  "enabled": true,
  "hour": 6,
  "minute": 30,
  "duration_ms": 20000,
  "speed_percent": 80,
  "next_run": 1706522400,
  "next_run_str": "2024-01-29 06:30:00",
  "last_run": 1706436000
}

Global Scheduler Status

Published every minute when connected.

Topic: plant_watering/schedule/status

Format:

{
  "holiday_mode": false,
  "time_sync": true,
  "active_schedules": 3,
  "time": 1706436000
}

Current System Time

Check or monitor the device's current time.

Get Time (On Demand)

  • Topic: plant_watering/commands/get_time
  • Payload: Any value (e.g., "1")
  • Response Topic: plant_watering/system/time
# Request current time
mosquitto_pub -h <broker> -t "plant_watering/commands/get_time" -m "1"

Response:

{
  "timestamp": 1706436000,
  "datetime": "2024-01-28 14:32:45 MST",
  "timezone": "MST7MDT,M3.2.0,M11.1.0",
  "synced": true
}

Periodic Time (Every Minute)

  • Topic: plant_watering/system/current_time

Format:

{
  "timestamp": 1706436000,
  "datetime": "2024-01-28 14:32:00 MST",
  "day_of_week": 0,
  "hour": 14,
  "minute": 32
}

Holiday Mode

Pause all schedules without deleting them.

Topic: plant_watering/commands/holiday_mode Payload: on or off

# Enable holiday mode
mosquitto_pub -h <broker> -t "plant_watering/commands/holiday_mode" -m "on"

# Disable holiday mode
mosquitto_pub -h <broker> -t "plant_watering/commands/holiday_mode" -m "off"

Manual Time Setting

If NTP is unavailable, set time manually.

Topic: plant_watering/schedule/time/set Payload: Unix timestamp (as string)

# Set current time
mosquitto_pub -h <broker> -t "plant_watering/schedule/time/set" -m "$(date +%s)"

Manual Schedule Trigger

Test schedules without waiting.

Topic: plant_watering/schedule/[pump_id]/trigger

# Trigger all enabled schedules for pump 1
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/trigger" -m "1"

Schedule Execution Notification

Published when a schedule executes.

Topic: plant_watering/schedule/[pump_id]/executed

Format:

{
  "schedule_id": 0,
  "duration_ms": 20000,
  "speed": 80
}

Example Configurations

Example 1: Morning and Evening Watering

# Morning watering at 6:30 AM
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/0/config" -m '{
  "type": "time_of_day",
  "enabled": true,
  "hour": 6,
  "minute": 30,
  "duration_ms": 15000,
  "speed_percent": 70
}'

# Evening watering at 6:30 PM
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/1/config" -m '{
  "type": "time_of_day",
  "enabled": true,
  "hour": 18,
  "minute": 30,
  "duration_ms": 15000,
  "speed_percent": 70
}'

Example 2: Every 2 Hours During Day

# Interval watering every 2 hours
mosquitto_pub -h <broker> -t "plant_watering/schedule/2/0/config" -m '{
  "type": "interval",
  "enabled": true,
  "interval_minutes": 120,
  "duration_ms": 10000,
  "speed_percent": 60
}'

Example 3: Weekday Morning Watering

# Water Monday-Friday at 7:00 AM
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/2/config" -m '{
  "type": "days_time",
  "enabled": true,
  "hour": 7,
  "minute": 0,
  "days_mask": 62,
  "duration_ms": 20000,
  "speed_percent": 80
}'

Example 4: Different Weekend Schedule

# Weekend watering at 9:00 AM with longer duration
mosquitto_pub -h <broker> -t "plant_watering/schedule/1/3/config" -m '{
  "type": "days_time",
  "enabled": true,
  "hour": 9,
  "minute": 0,
  "days_mask": 65,
  "duration_ms": 30000,
  "speed_percent": 75
}'

Disable/Enable Schedules

To disable a schedule without deleting it:

mosquitto_pub -h <broker> -t "plant_watering/schedule/1/0/config" -m '{
  "type": "time_of_day",
  "enabled": false,
  "hour": 6,
  "minute": 30,
  "duration_ms": 20000,
  "speed_percent": 80
}'

To completely remove a schedule:

mosquitto_pub -h <broker> -t "plant_watering/schedule/1/0/config" -m '{
  "type": "disabled"
}'

Time Zone Configuration

The scheduler uses Mountain Time (MST/MDT) by default. To change:

  1. Edit scheduler.c in the scheduler_init() function:
// Set timezone (adjust as needed)
setenv("TZ", "PST8PDT,M3.2.0,M11.1.0", 1);  // Pacific Time
setenv("TZ", "EST5EDT,M3.2.0,M11.1.0", 1);  // Eastern Time
setenv("TZ", "CST6CDT,M3.2.0,M11.1.0", 1);  // Central Time
setenv("TZ", "GMT0BST,M3.5.0,M10.5.0", 1);  // UK Time

Serial Monitor Output

The system status is printed to serial every 30 seconds, including:

I (xxxxx) MAIN: Scheduler: 2 active, Holiday: OFF, DateTime: 2024-01-28 14:32:45

Troubleshooting

Time Not Synchronized

  • Check internet connection
  • Verify NTP servers are accessible
  • Manual set time as workaround
  • Check serial output for sync status

Schedule Not Executing

  1. Check if time is synchronized
  2. Verify schedule is enabled
  3. Check holiday mode is off
  4. Verify schedule configuration is valid
  5. Check pump isn't in cooldown period
  6. Monitor execution notifications on MQTT

Schedule Executes at Wrong Time

  • Verify timezone setting
  • Check system time is correct
  • Remember schedules won't run twice within 60 seconds
  • Use get_time command to verify device time

Integration with Automation

The scheduler can work alongside moisture-based automation:

  • Schedules provide baseline watering
  • Moisture sensors can trigger additional watering
  • Both respect motor safety limits (max runtime, cooldown)

Best Practices

  1. Test Schedules: Use manual trigger to test before relying on schedule
  2. Start Simple: Begin with one schedule and add more as needed
  3. Monitor Execution: Watch MQTT topics to confirm schedules work
  4. Use Holiday Mode: Don't delete schedules when going away
  5. Stagger Schedules: If using multiple pumps, offset times to reduce load
  6. Monitor Time Sync: Ensure device maintains correct time

Implementation Notes

  • No External Dependencies: The scheduler uses built-in JSON parsing instead of cJSON library
  • Time Check Interval: Schedules are checked every 30 seconds
  • Execution Window: Schedules execute within 60 seconds of target time
  • NTP Servers: Uses pool.ntp.org, time.nist.gov, and time.google.com
  • Persistence: Schedule configurations saved to NVS, runtime info is not persisted

Limitations

  • Maximum 4 schedules per pump (8 total)
  • Minimum resolution is 1 minute
  • Schedules check every 30 seconds (may be up to 30s late)
  • All times are in configured timezone
  • Requires accurate system time (NTP or manual)
  • Simple JSON parser has basic error handling