# 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. ```json { "type": "interval", "enabled": true, "interval_minutes": 120, "duration_ms": 15000, "speed_percent": 70 } ``` #### 2. Time of Day Schedule Waters daily at a specific time. ```json { "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. ```json { "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 ```bash mosquitto_pub -h -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") ```bash # Request all schedules mosquitto_pub -h -t "plant_watering/commands/get_schedules" -m "1" # Monitor the responses mosquitto_sub -h -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: ```json { "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 ```bash # Get all schedules for pump 1 mosquitto_pub -h -t "plant_watering/schedule/1/get" -m "1" # Get all schedules for pump 2 mosquitto_pub -h -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**: ```json { "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**: ```json { "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` ```bash # Request current time mosquitto_pub -h -t "plant_watering/commands/get_time" -m "1" ``` Response: ```json { "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: ```json { "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` ```bash # Enable holiday mode mosquitto_pub -h -t "plant_watering/commands/holiday_mode" -m "on" # Disable holiday mode mosquitto_pub -h -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) ```bash # Set current time mosquitto_pub -h -t "plant_watering/schedule/time/set" -m "$(date +%s)" ``` ### Manual Schedule Trigger Test schedules without waiting. **Topic**: `plant_watering/schedule/[pump_id]/trigger` ```bash # Trigger all enabled schedules for pump 1 mosquitto_pub -h -t "plant_watering/schedule/1/trigger" -m "1" ``` ### Schedule Execution Notification Published when a schedule executes. **Topic**: `plant_watering/schedule/[pump_id]/executed` **Format**: ```json { "schedule_id": 0, "duration_ms": 20000, "speed": 80 } ``` ## Example Configurations ### Example 1: Morning and Evening Watering ```bash # Morning watering at 6:30 AM mosquitto_pub -h -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 -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 ```bash # Interval watering every 2 hours mosquitto_pub -h -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 ```bash # Water Monday-Friday at 7:00 AM mosquitto_pub -h -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 ```bash # Weekend watering at 9:00 AM with longer duration mosquitto_pub -h -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: ```bash mosquitto_pub -h -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: ```bash mosquitto_pub -h -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: ```c // 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