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

422 lines
9.9 KiB
Markdown

# 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 <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")
```bash
# 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:
```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 <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**:
```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 <broker> -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 <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)
```bash
# 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`
```bash
# 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**:
```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 <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
```bash
# 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
```bash
# 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
```bash
# 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:
```bash
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:
```bash
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:
```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