Comprehensive guide for creating and deploying JavaScript automation scripts to Shelly devices using template-based configuration.
Shelly Script Templates are pre-built JavaScript automation scripts that can be deployed directly to Shelly devices (Gen 2/3). These scripts run autonomously on the device itself, requiring no external server or cloud connection.
Key Benefits:
- No Cloud Dependency: Scripts execute locally on the Shelly device
- Privacy-First: All automation logic stays on your local network
- Parameterized: Configure scripts through a user-friendly interface without writing code
- Reliable: Scripts continue running even if your phone/computer is offline
- Versioned: Templates support semantic versioning with automatic update detection
- Template Definition (
assets/script_templates/*.json): JSON files defining script structure, parameters, and source code - Parameter Configuration: User fills in required/optional parameters through the app UI
- Code Generation: App adds parameter on top in source code
- Atomic Deployment: Script uploaded with staging process and failure recovery
- Runtime Execution: JavaScript executes on Shelly device using Shelly's scripting engine
- Open a Shelly device from your device list
- Tap the menu button (three dots) in the top right
- Select "Scripts" from the menu
- Tap the "Add" button (+ icon)
- Select "From Template"
- Browse available templates
- Templates are filtered based on your device compatibility
- Templates requiring other devices (e.g., Zendure) only appear if you have them in your device list
The parameter configuration screen shows:
- Required Parameters: Marked with an asterisk, must be filled
- Optional Parameters: Can be left at default values
- Advanced Parameters: Hidden by default (enable Expert Mode in settings to show)
- Auto-Populated Fields: Automatically filled from your existing devices (IP addresses, serial numbers)
Parameter Configuration Tips:
- Look for the info icon (ℹ️) next to parameters for detailed descriptions
- Green checkmark: Value auto-populated from device list
- Orange warning: No matching device found for auto-population
- Search icon: Multiple devices found, tap to select one
You have two deployment options:
Preview (Recommended for first-time users):
- Tap "Vorschau" (Preview)
- Review the generated JavaScript code
- Verify all parameters are correctly inserted
- Tap "Installieren" to deploy
Direct Install (For experienced users):
- Tap "Direkt installieren" (Direct Install)
- Confirm the installation
- Script is immediately deployed to the device
The deployment process uses atomic staging:
- Creating Script: Script created with staging name
__auto_{template}_ 0.0.0_{id} - Uploading Code: JavaScript code uploaded to device
- Finalizing: If successful, script renamed to
__auto_{template}_{version}_{id} - Enabling & Starting: Script enabled and started automatically
If deployment fails:
- Script remains at version "0.0.0" with red "Fehlgeschlagen" (Failed) badge
- Error message explains what went wrong
- Tap the script to access repair options
Automatically balance Zendure power station output/input based on real-time grid measurements from Shelly EM3 for zero-export operation.
Key Features:
- Automatic zero-export/nulleinspeisung control
- Bidirectional operation (discharge to home, charge from excess)
- Battery SOC protection and bypass mode handling
- Two variants: IP/WiFi and MAC/Bluetooth
Hardware Requirements:
- Shelly EM3 (three-phase energy meter)
- Zendure Power Station (ACE 1500, SolarFlow, HUB, etc.)
- Network connection (WiFi/LAN)
📖 For detailed documentation including parameter reference, configuration examples, deployment guide, and troubleshooting, see ZENDURE_POWER_CONTROL.md.
Automatically adjust OpenDTU inverter power limits based on real-time grid measurements from Shelly EM3 for zero-export operation.
Key Features:
- Automatic zero-export/nulleinspeisung control for OpenDTU-managed inverters
- Dynamic power limit adjustment based on grid feedback
- Support for Hoymiles, DeyeSun, and other OpenDTU-compatible inverters
- Configurable input divider for multi-input inverters
Hardware Requirements:
- Shelly EM3 (three-phase energy meter)
- OpenDTU device with connected micro inverter
- Network connection (WiFi/LAN)
Automated data reporting to online monitoring platforms for Zendure power stations.
Key Features:
- Periodic data upload to online monitoring platforms
- Support for multiple monitoring services simultaneously
- Configurable intervals and data points
- Three variants: IP/WiFi, MAC/Bluetooth, and auto-discovery
Hardware Requirements:
- Zendure Power Station (ACE 1500, SolarFlow, HUB, etc.)
- Network connection (WiFi/LAN)
- Online monitoring account
Compatible Monitoring Platform:
- Solar Monitoring - Open-source solar monitoring platform
- Live instances: solar.pihost.org / solar.tost-soft.de
- Open Shelly device → Menu → "Scripts"
- View list of all scripts on the device:
- Script name: Shows template ID, version, and deployment ID
- Status indicator: Green (running), gray (stopped)
- Version badge: Template version number
- Update badge: Orange "Update" badge if newer template version available
- Tap on a script in the list
- Select "Parameter aktualisieren" (Update Parameters)
- Modify parameter values
- Tap "Aktualisieren" to deploy updated script
Note: Script is regenerated with new parameters and re-uploaded using atomic deployment.
When a newer template version is available:
- Script shows orange "Update verfügbar" badge
- Tap the script
- Select "Auf Version X.X.X upgraden"
- Review new parameters (any new parameters are highlighted)
- Confirm upgrade
Atomic Upgrade Process:
- Existing parameters are preserved
- New parameters use default values (you can customize them)
- Script transitions through staging (0.0.0) during upgrade
- On success, renamed to new version
If a script shows red "Fehlgeschlagen" badge:
-
Identify the Problem:
- Check error message displayed during deployment
- Common causes: network timeout, invalid parameters, Shelly device busy
-
Repair Options:
- Update Parameters: Fix incorrect values and redeploy
- Reinstall: Delete and create new script from template
- Check Connectivity: Ensure Shelly device is reachable
-
Debug Steps:
- Enable DEBUG parameter and check Shelly device logs
- Verify target device (e.g., Zendure) is reachable from Shelly
- Test HTTP endpoints manually using curl/Postman
- Swipe left on script in list, or
- Tap script → Menu → "Löschen"
- Confirm deletion
Note: Deleted scripts are removed permanently from the Shelly device.
Create a new file in assets/script_templates/ with this structure:
{
"id": "my-template",
"name": "My Custom Template",
"version": "1.0.0",
"description": "Brief description of what this script does",
"compatibleDevices": ["SPEM", "SNPL"],
"requiredDevices": [],
"author": "Your Name",
"tags": ["automation", "monitoring"],
"parameters": [
{
"name": "PARAM_NAME",
"label": "Parameter Label",
"description": "Help text for the user",
"type": "string",
"required": true,
"defaultValue": "default",
"placeholder": "Example value"
}
],
"sourceCode": "JavaScript code",
"createdAt": "2025-01-15T00:00:00Z",
"updatedAt": "2025-01-15T00:00:00Z"
}| Type | Description | Validation | Example |
|---|---|---|---|
| string | Text value | None (optional regex pattern) | "Hello World" |
| number | Integer value | Min/max value optional | 42 |
| boolean | True/false | None | true |
| url | HTTP/HTTPS URL | Must match URL pattern | "http://example.com" |
| port | Network port | 1-65535 | 8080 |
| duration | Time in milliseconds | Min/max value | 10000 |
| deviceName | Device identifier | None | "shelly-plug-kitchen" |
Parameters can automatically pull values from existing devices in the user's device list:
{
"name": "DEVICE_IP",
"label": "Device IP Address",
"type": "string",
"required": true,
"sourceConfig": {
"source": "device",
"sourceProperty": "ipAddress",
"sourceFilter": "zendure"
}
}Source Configuration:
source: Always "device" (future: "system", "global")sourceProperty: Property to extract (ipAddress,serialNumber,macAddress, etc.)sourceFilter: Device manufacturer filter (zendure,shelly,opendtu, etc.)
Auto-Population Behavior:
- 0 devices: Field empty, user must manually enter
- 1 device: Field auto-filled with value
- Multiple devices: Search button appears, user selects from list
let host = "{{HOST}}";
let port = {{PORT}};
let enabled = {{ENABLE_FEATURE}};Important: Boolean and number parameters should NOT be quoted - they're inserted as JavaScript literals.
{
"name": "ADVANCED_PARAM",
"label": "Advanced Setting",
"type": "number",
"required": false,
"defaultValue": 100,
"minValue": 10,
"maxValue": 1000,
"advancedOption": true,
"validationPattern": "^[0-9]+$",
"validationErrorMessage": "Must be a positive number"
}Options:
advancedOption: Hide unless Expert Mode enabledvalidationPattern: Regex pattern for validation (string types only)validationErrorMessage: Custom error message for validation failureminValue/maxValue: Numeric range validation
Use semantic versioning (MAJOR.MINOR.PATCH):
- MAJOR: Breaking changes (parameter removed/renamed, behavior changed)
- MINOR: New features (new optional parameters, enhanced functionality)
- PATCH: Bug fixes (no new parameters, same behavior)
The app automatically detects version updates and prompts users to upgrade deployed scripts.
- Place JSON file in
assets/script_templates/ - Restart the app (hot reload may not pick up asset changes)
- Open compatible Shelly device → Scripts → From Template
- Verify your template appears in the list
- Test deployment with various parameter combinations
- Check Shelly device logs for runtime errors
Plain text value, optionally with regex validation.
{
"name": "API_KEY",
"type": "string",
"required": true,
"placeholder": "Enter your API key",
"validationPattern": "^[A-Za-z0-9]{32}$",
"validationErrorMessage": "API key must be 32 alphanumeric characters"
}Integer value with optional min/max constraints.
{
"name": "TIMEOUT",
"type": "number",
"defaultValue": 30,
"minValue": 1,
"maxValue": 300
}True/false value, rendered as a switch in UI.
{
"name": "ENABLE_NOTIFICATIONS",
"type": "boolean",
"defaultValue": true
}HTTP or HTTPS URL with automatic validation.
{
"name": "BACKEND_URL",
"type": "url",
"placeholder": "http://your-server:8080/api"
}Network port number (1-65535).
{
"name": "SERVER_PORT",
"type": "port",
"defaultValue": 8080
}Time duration in milliseconds with optional range.
{
"name": "POLLING_INTERVAL",
"type": "duration",
"defaultValue": 10000,
"minValue": 1000,
"maxValue": 300000
}UI Rendering: Shows "ms" suffix in input field.
Device identifier/name for tagging in external systems.
{
"name": "DEVICE_ID",
"type": "deviceName",
"placeholder": "shelly-plug-office"
}- Test incrementally: Start with minimal functionality, add features gradually
- Use debug logging: Add
print()statements, enable DEBUG parameter - Handle errors gracefully: Check for null/undefined, validate responses
- Avoid busy loops: Use timers instead of while loops
- Monitor memory: Shelly devices have limited RAM (check
Shelly.getSystemInfo())
- Required vs Optional: Only mark truly essential parameters as required
- Sensible defaults: Provide working defaults for optional parameters
- Clear descriptions: Explain what each parameter does and acceptable values
- Use advanced flag: Hide complexity from basic users
- Auto-population: Leverage sourceConfig to reduce manual data entry
- Batch API calls: Minimize HTTP requests in tight loops
- Cache values: Store frequently accessed data in variables
- Debounce updates: Use hysteresis to prevent rapid switching
- Timer intervals: Balance responsiveness vs resource usage
- No secrets in templates: Don't hardcode API keys or passwords
- Validate inputs: Check parameter values before use
- HTTPS preferred: Use HTTPS for external API calls when possible
- Network isolation: Scripts run on local network, can't access external WAN by default
Symptoms: Script shows as stopped, won't enable
Solutions:
- Check Shelly device logs for syntax errors
- Verify all required Shelly services are enabled
- Ensure script doesn't exceed memory limits
- Try deploying a simpler test script to isolate the issue
Symptoms: Script starts but stops after some time
Solutions:
- Check for unhandled JavaScript exceptions
- Monitor memory usage (add periodic
print(Shelly.getSystemInfo().ram_free)) - Verify external devices (e.g., Zendure) remain reachable
- Check if Shelly device firmware is up to date
Symptoms: Script runs but doesn't behave as configured
Solutions:
- Enable DEBUG parameter to see actual values
- Check parameter names match exactly (case-sensitive)
- Verify placeholder syntax
{{PARAM_NAME}}is correct - Use preview mode to inspect generated code
Symptoms: Expected device value not auto-filled
Solutions:
- Verify device exists in device list
- Check
sourceFiltermatches device manufacturer exactly - Ensure device has the requested property (e.g.,
ipAddress) - Try manually entering value to isolate auto-population vs runtime issue
Made with ☀️ for a sustainable energy future