Added Scheduler
This commit is contained in:
422
SCHEDULER_README.md
Normal file
422
SCHEDULER_README.md
Normal file
@ -0,0 +1,422 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user