Automations
About Automations
The Automation module provides comprehensive functionality for managing device automations across multiple nodes in the ESP RainMaker system. It allows users to create, edit, and manage automations that can control multiple devices based on specific events and conditions.
User Flow Overview
The Automation module has three main user flows:
- Create New Automation: Automations → CreateAutomation → Configure Event → Configure Actions
- Edit Existing Automation: Automations → CreateAutomation (with data) → Modify → Save
- Enable/Disable Automation: Toggle automation state directly from list
Architecture Overview
Components Structure
The automation module consists of the following components:
(automation)/
├── _layout.tsx # Navigation and context setup
├── Automations.tsx # Main automation list screen
├── CreateAutomation.tsx # Create/edit automation screen
├── EventDeviceSelection.tsx # Choose event trigger device
├── EventDeviceParamSelection.tsx # Configure event parameters
├── ActionDeviceSelection.tsx # Choose action devices
└── ActionDeviceParamSelection.tsx # Configure action parameters
Implementation Details
1. Automations List (Automations.tsx)
The main screen for managing automations:
// Get CDF stores
const { store } = useCDF();
const { automationStore, groupStore } = store;
// Get automation list from CDF
const { nodeAutomationList } = automationStore;
// Fetch and sync automations
const loadAutomations = async () => {
await automationStore.syncAutomationList();
};
2. Event Configuration
Event configuration involves two steps:
// Step 1: Select Event Device
const handleDeviceSelect = (device: DeviceSelectionData) => {
setSelectedEventDevice({
nodeId: device.node.id,
deviceName: device.device.name,
displayName: device.device.displayName
});
};
// Step 2: Configure Event Parameters
const handleCreateEvent = async () => {
const automationEvent = {
deviceName: selectedDevice.name,
param: activeEventParam,
check: eventCondition,
value: eventValue
};
addEvent(automationEvent);
};
3. Action Configuration
Action configuration also involves two steps:
// Step 1: Select Action Device
const handleDeviceSelect = (device: DeviceSelectionData) => {
setSelectedDevice({
nodeId: device.node.id,
deviceName: device.device.name,
displayName: device.device.displayName
});
};
// Step 2: Configure Action Parameters
const handleParamSave = () => {
setActionValue(
nodeId,
selectedDevice.name,
selectedParam.name,
selectedParam.value
);
};
CDF API Usage Summary
1. Automation Store Operations
// Get all automations
const { nodeAutomationList } = automationStore;
// Create new automation
await automationStore.createAutomation(automationDetails);
// Update automation
await automation.update(updates);
// Delete automation
await automation.delete();
// Enable/Disable automation
await automation.enable(enabled);
// Sync automations
await automationStore.syncAutomationList();
2. Automation Data Structure
// Automation Event Format
interface AutomationEvent {
deviceName: string; // Device name that triggers the automation
param: string; // Parameter name to monitor
check: string; // Comparison operator (==, !=, >, <, >=, <=)
value: any; // Value to compare against
}
// Automation Action Format
interface AutomationAction {
[nodeId: string]: {
[deviceName: string]: {
[paramName: string]: any; // Parameter value to set
};
};
}
// Automation Configuration
interface AutomationConfig {
id: string; // Unique automation ID
name: string; // Automation name
enabled: boolean; // Whether automation is active
event: AutomationEvent; // Trigger event configuration
actions: AutomationAction; // Actions to execute
retrigger: boolean; // Whether to retrigger when conditions are met again
}
3. Automation Operations Examples
// Create new automation
const automationData = {
id: generateRandomId(),
name: "Turn on lights when motion detected",
enabled: true,
event: {
deviceName: "motion_sensor",
param: "motion",
check: "==",
value: true
},
actions: {
"node123": {
"light": {
"power": true,
"brightness": 80
}
}
},
retrigger: false
};
await automationStore.createAutomation(automationData);
// Enable/Disable automation
const automation = automationStore.automationsByID[automationId];
await automation.enable(true); // Enable
await automation.enable(false); // Disable
// Update automation
await automation.update({
name: "Updated automation name",
event: { /* updated event */ },
actions: { /* updated actions */ }
});
// Delete automation
await automation.delete();
Key Differences from Scenes
- Event-Based Triggers: Unlike scenes which are manually triggered, automations run based on device events
- Conditional Logic: Supports operators like equals, greater than, less than, not equals, greater than or equals, less than or equals for event triggers
- Retrigger Option: Can be configured to repeat when conditions are met again
- Multi-Step Flow: Requires event configuration before action setup
- State Management: More complex due to event conditions and trigger logic
Data Flow Summary
Create New Automation Flow
- User initiates creation in Automations.tsx
- Configure name and retrigger in CreateAutomation.tsx
- Select trigger device in EventDeviceSelection.tsx
- Configure conditions in EventDeviceParamSelection.tsx
- Select action devices in ActionDeviceSelection.tsx
- Configure actions in ActionDeviceParamSelection.tsx
- Save using CDF automationStore.createAutomation()
Edit Existing Automation Flow
- User selects edit in Automations.tsx
- Load existing data in CreateAutomation.tsx
- Modify events, actions, or settings
- Save changes using CDF automation.update()
Common Patterns
Automation Creation Pattern:
// 1. Initialize automation state
const [automationName, setAutomationName] = useState("");
const [event, setEvent] = useState<AutomationEvent | null>(null);
const [actions, setActions] = useState<AutomationAction>({});
const [retrigger, setRetrigger] = useState(false);
// 2. Configure event (trigger)
const handleEventConfigure = (device: ESPRMDevice, param: ESPRMParam, check: string, value: any) => {
setEvent({
deviceName: device.name,
param: param.name,
check,
value
});
};
// 3. Configure actions
const handleActionConfigure = (nodeId: string, deviceName: string, paramName: string, value: any) => {
setActions(prev => ({
...prev,
[nodeId]: {
...prev[nodeId],
[deviceName]: {
...prev[nodeId]?.[deviceName],
[paramName]: value
}
}
}));
};
// 4. Save automation
const handleSave = async () => {
const automationData = {
id: generateRandomId(),
name: automationName,
enabled: true,
event: event!,
actions,
retrigger
};
await automationStore.createAutomation(automationData);
};
Automation Toggle Pattern:
const handleToggleAutomation = async (automationId: string, enabled: boolean) => {
const automation = automationStore.automationsByID[automationId];
if (automation) {
await automation.enable(enabled);
toast.showSuccess(
enabled ? "Automation enabled" : "Automation disabled"
);
}
};
Error Handling Pattern:
try {
const result = await automationStore.createAutomation(automationData);
if (result?.status === "success") {
toast.showSuccess("Automation created successfully");
} else {
toast.showError(result.description || "Failed to create automation");
}
} catch (error) {
console.error("Error creating automation:", error);
toast.showError("Failed to create automation");
}
Key Takeaways
- Event-Driven: Based on device parameter conditions
- Multi-Device Support: Can involve multiple devices for both events and actions
- Conditional Logic: Supports various comparison operators (
==,!=,>,<,>=,<=) - Retrigger Capability: Can repeat when conditions are met again
- CDF Integration: All automation operations use CDF automationStore
- State Management: Automation state is managed through automation context
- Async Operations: All CDF operations are async with proper error handling