A complete timed/scheduled commands system that allows users to schedule future commands from the web dashboard (e.g., "in 10 minutes, spray pesticide").
src/lib/services/scheduled-command.service.ts- Service layer for scheduled commandssrc/lib/scheduler.ts- Background worker that executes due commands every 30 secondsapp/api/channels/[id]/scheduled-commands/route.ts- API endpoint to create scheduled commandsapp/api/scheduled-commands/[id]/route.ts- API endpoint to cancel scheduled commandsdrizzle/0001_add_scheduled_commands.sql- Database migration for new tableSCHEDULED_COMMANDS.md- Feature documentationIMPLEMENTATION_SUMMARY.md- This file
src/lib/db/schema.ts- AddedscheduledCommandstable definitionsrc/lib/types.ts- AddedScheduledCommandViewtype and updatedControllerSnapshotsrc/lib/validators.ts- AddedscheduledCommandSchemavalidatorsrc/lib/data.ts- Exported scheduled command service functionssrc/lib/services/snapshot.service.ts- Added scheduled commands to controller snapshotserver.ts- Initialize scheduler on server startupsrc/components/dashboard/controller-detail.tsx- Added Scheduled Commands Panel UI
- New
scheduled_commandstable with indexes - Tracks pending, executed, cancelled, and failed commands
- Links to channels, controllers, users, and executed commands
- Runs every 30 seconds to check for due commands
- Automatically executes commands at scheduled time
- Handles failures gracefully
- Cleans up old commands (30+ days) daily
- POST
/api/channels/[channelId]/scheduled-commands- Schedule a command - DELETE
/api/scheduled-commands/[id]- Cancel a pending command
- Schedule form with channel selection, action (on/off), date/time picker, and notes
- List of pending commands with cancel buttons
- History of executed/cancelled/failed commands
- Default time set to 10 minutes in the future
- Works with existing MQTT infrastructure
- Uses existing
createManualCommand()for execution - Respects user permissions and controller ownership
- Integrates with RTC module on hardware
- User schedules a command via the web dashboard
- Command is stored in the database with status
pending - Background scheduler checks every 30 seconds for due commands
- When time arrives, scheduler calls
createManualCommand()to execute - Command is sent to device via MQTT (same as manual commands)
- Device acknowledges and executes the command
- Status is updated to
executed(orfailedif error occurs)
npm run migrateThis creates the scheduled_commands table.
- Start the server:
npm run devornpm start - Navigate to a controller detail page
- Click "Schedule" in the Scheduled Commands section
- Schedule a command for 1-2 minutes in the future
- Wait and verify it executes
Watch for scheduler activity in server logs:
[Scheduler] Starting scheduled command processor
[Scheduler] Processed 1 commands: succeeded=1, failed=0
- Pesticide spraying: "In 10 minutes, turn on spray pump for 15 minutes"
- Irrigation scheduling: "Tomorrow at 6:00 AM, turn on irrigation valve"
- UV zapper timing: "Tonight at 8:00 PM, turn on UV zapper"
- Maintenance windows: "In 1 hour, turn off all pumps for maintenance"
- Scheduler runs in the same process as the web server
- Commands execute within 30 seconds of scheduled time (scheduler interval)
- Only actuator/hybrid channels can be scheduled (sensors are read-only)
- Scheduled commands require server to be running at execution time
- If server is down, commands execute when it restarts (if still due)
- All scheduled commands respect user permissions and controller ownership
Consider adding:
- Recurring schedules (daily, weekly)
- Conditional execution (based on sensor readings)
- Command sequences/chains
- Time zone support
- Email/push notifications
- Bulk scheduling