Shelly Core
The Shelly Core provides fundamental methods for interacting with the device, including RPC calls, event handling, component status, and device information. This is the primary API for controlling and monitoring your Shelly device from scripts.
Overview
The Shelly API enables scripts to:
- Execute RPC methods to control device components
- Listen for device events and status changes
- Read component configuration and status
- Access device information
- Emit custom events
- Measure uptime
Quick Example
// Control a switch
Shelly.call("Switch.Set", {id: 0, on: true}, function(result, error_code) {
if (error_code === 0) {
console.log("Switch turned on");
}
});
// Listen for button presses
Shelly.addEventHandler(function(event) {
if (event.component === "input:0" && event.info.event === "single_push") {
console.log("Button pressed!");
// React to button press
Shelly.call("Switch.Toggle", {id: 0});
}
});
// Get temperature reading
let temp = Shelly.getComponentStatus("temperature:0");
if (temp) {
console.log("Temperature:", temp.tC, "°C");
}
API Reference
Script Object
The Script object provides access to script-specific information and storage.
Script.id
The ID of the currently running script instance.
console.log("This is script ID:", Script.id);
Script.storage
Since version 1.5.0
Persistent key-value storage for the script, implementing the Web Storage API.
Storage Limits:
- Maximum key length: 16 bytes
- Maximum value length: 1024 bytes
- Maximum number of items: 12
Important Notes:
- Storage is unique to each script
- Storage is cleared when the script is deleted
- Storage is cleared on factory reset
- Only string values are supported
// Store a value
Script.storage.setItem('counter', JSON.stringify(42));
// Retrieve a value
let counter = Script.storage.getItem('counter');
if (counter !== null) {
counter = JSON.parse(counter);
console.log("Counter value:", counter);
}
// Remove a value
Script.storage.removeItem('counter');
// Clear all storage
Script.storage.clear();
// Iterate over all items
for (let i = 0; i < Script.storage.length; i++) {
const key = Script.storage.key(i);
const value = Script.storage.getItem(key);
console.log(key, ":", value);
}
Shelly Object
The Shelly object provides methods for device interaction.
Shelly.call()
Invokes RPC methods on the local device.
Shelly.call(method, params[, callback[, userdata]]) -> undefined
Parameters
| Property | Type | Description | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| string | Name of the RPC method to invoke | |||||||||||||||
| object or null | Parameters for the method | |||||||||||||||
| function | Optional callback function
| |||||||||||||||
| any | Optional data passed to callback |
Examples
// Simple switch control
Shelly.call("Switch.Set", {id: 0, on: true});
// With callback
Shelly.call("Switch.GetStatus", {id: 0}, function(result, error_code, error_message) {
if (error_code === 0) {
console.log("Switch is", result.output ? "on" : "off");
} else {
console.log("Error:", error_message);
}
});
// With userdata
Shelly.call("HTTP.GET", {url: "http://api.example.com"},
function(result, error_code, error_message, context) {
console.log("Request", context.requestId, "completed");
},
{requestId: 123}
);
Shelly.addEventHandler()
Subscribes to device events (same as RPC NotifyEvent).
Shelly.addEventHandler(callback[, userdata]) -> subscription_handle
Parameters
| Property | Type | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| function | Function called when event occurs
| |||||||||
| any | Optional data passed to callback |
Return Value
Returns a subscription handle for later removal.
Example
let eventHandle = Shelly.addEventHandler(function(event, ud) {
console.log("Event from", event.component, ":", event.event);
// Handle specific events
if (event.component === "input:0") {
if (event.info.event === "single_push") {
console.log("Single press on input 0");
} else if (event.info.event === "double_push") {
console.log("Double press on input 0");
}
}
// Handle switch events
if (event.component === "switch:0") {
console.log("Switch 0 state changed to", event.info.state);
}
});
Shelly.addStatusHandler()
Subscribes to device status changes (same as RPC NotifyStatus).
Shelly.addStatusHandler(callback[, userdata]) -> subscription_handle
Parameters and return value are identical to addEventHandler.
Example
let statusHandle = Shelly.addStatusHandler(function(status, ud) {
console.log("Status update from", status.component);
// Monitor temperature changes
if (status.component === "temperature:0") {
console.log("Temperature:", status.delta.tC, "°C");
}
// Monitor power consumption
if (status.component === "switch:0" && status.delta.apower !== undefined) {
console.log("Power consumption:", status.delta.apower, "W");
}
});
Shelly.removeEventHandler()
Removes an event subscription.
Shelly.removeEventHandler(subscription_handle) -> boolean
Returns true if handler was removed, false if not found, undefined for invalid handle.
// Remove the event handler
if (Shelly.removeEventHandler(eventHandle)) {
console.log("Event handler removed");
}
Shelly.removeStatusHandler()
Removes a status subscription.
Shelly.removeStatusHandler(subscription_handle) -> boolean
Returns true if handler was removed, false if not found, undefined for invalid handle.
Shelly.emitEvent()
Creates a custom event that is broadcast to all RPC channels.
Shelly.emitEvent(name, data) -> undefined
Parameters
| Property | Type | Description |
|---|---|---|
| string | Name of the custom event |
| any | Event data (must be JSON-serializable) |
Example
// Emit a custom event
Shelly.emitEvent("temperature_alert", {
temperature: 45.2,
threshold: 40,
message: "High temperature detected"
});
// This will generate a notification:
// {
// "component": "script:1",
// "id": 1,
// "event": "temperature_alert",
// "data": {
// "temperature": 45.2,
// "threshold": 40,
// "message": "High temperature detected"
// },
// "ts": 1657878122.44
// }
Shelly.getComponentConfig()
Gets the configuration of a component.
Shelly.getComponentConfig(type_or_key, id) -> object or null
Parameters
| Property | Type | Description |
|---|---|---|
| string | Component type (e.g., "switch") or full key (e.g., "switch:0") |
| number | Component ID (optional if using full key) |
Return Value
Returns configuration object or null if component not found.
Examples
// Get switch configuration
let switchConfig = Shelly.getComponentConfig("switch", 0);
console.log("Switch name:", switchConfig.name);
// Using full key
let inputConfig = Shelly.getComponentConfig("input:0");
console.log("Input type:", inputConfig.type);
// Get system configuration
let sysConfig = Shelly.getComponentConfig("sys");
console.log("Device name:", sysConfig.device.name);
console.log("Time server:", sysConfig.sntp.server);
Shelly.getComponentStatus()
Gets the current status of a component.
Shelly.getComponentStatus(type_or_key, id) -> object or null
Parameters
| Property | Type | Description |
|---|---|---|
| string | Component type (e.g., "switch") or full key (e.g., "switch:0") |
| number | Component ID (optional if using full key) |
Return Value
Returns status object or null if component not found.
Examples
// Get switch status
let switchStatus = Shelly.getComponentStatus("switch", 0);
if (switchStatus) {
console.log("Switch is", switchStatus.output ? "ON" : "OFF");
console.log("Power:", switchStatus.apower, "W");
}
// Get temperature
let tempStatus = Shelly.getComponentStatus("temperature:0");
if (tempStatus) {
console.log("Temperature:", tempStatus.tC, "°C");
console.log("Fahrenheit:", tempStatus.tF, "°F");
}
// Get system status
let sysStatus = Shelly.getComponentStatus("sys");
console.log("Uptime:", sysStatus.uptime, "seconds");
console.log("RAM free:", sysStatus.ram_free, "bytes");
Shelly.getDeviceInfo()
Gets information about the device.
Shelly.getDeviceInfo() -> object
Return Value
Returns a DeviceInfo object containing:
id- Device IDmodel- Device modelmac- MAC addressfw_id- Firmware versionapp- Application name- And more device-specific information
Example
let deviceInfo = Shelly.getDeviceInfo();
console.log("Device ID:", deviceInfo.id);
console.log("Model:", deviceInfo.model);
console.log("MAC:", deviceInfo.mac);
console.log("Firmware:", deviceInfo.fw_id);
Shelly.getCurrentScriptId()
Gets the ID of the currently running script.
Shelly.getCurrentScriptId() -> number
Example
let scriptId = Shelly.getCurrentScriptId();
console.log("Running as script ID:", scriptId);
// Note: This is equivalent to Script.id
Shelly.getUptimeMs()
Gets the device uptime in milliseconds.
Shelly.getUptimeMs() -> number
Example
let uptime = Shelly.getUptimeMs();
console.log("Device has been running for", uptime, "ms");
console.log("That's", Math.floor(uptime / 1000 / 60), "minutes");
Complete Examples
Device Monitor
// Monitor device health
let monitoring = true;
// Check device status every minute
Timer.set(60000, true, function() {
if (!monitoring) return;
let sys = Shelly.getComponentStatus("sys");
let info = Shelly.getDeviceInfo();
// Check RAM usage
let ramUsagePercent = ((sys.ram_size - sys.ram_free) / sys.ram_size) * 100;
if (ramUsagePercent > 80) {
Shelly.emitEvent("high_memory_usage", {
used_percent: ramUsagePercent,
free_bytes: sys.ram_free
});
}
// Log status
console.log("Device:", info.id);
console.log("Uptime:", Math.floor(sys.uptime / 3600), "hours");
console.log("RAM usage:", ramUsagePercent.toFixed(1), "%");
console.log("Temperature:", sys.temperature, "°C");
});
// Handle events
Shelly.addEventHandler(function(event) {
console.log("Event:", event.event, "from", event.component);
});
Smart Switch Controller
// Smart switch with auto-off and power monitoring
const SWITCH_ID = 0;
const AUTO_OFF_DELAY = 30 * 60 * 1000; // 30 minutes
const MAX_POWER = 2000; // Watts
let autoOffTimer = null;
// Monitor switch state changes
Shelly.addEventHandler(function(event) {
if (event.component === "switch:" + SWITCH_ID) {
if (event.info.state === true) {
console.log("Switch turned ON");
// Set auto-off timer
if (autoOffTimer) Timer.clear(autoOffTimer);
autoOffTimer = Timer.set(AUTO_OFF_DELAY, false, function() {
console.log("Auto-off triggered");
Shelly.call("Switch.Set", {id: SWITCH_ID, on: false});
autoOffTimer = null;
});
} else {
console.log("Switch turned OFF");
// Cancel auto-off timer
if (autoOffTimer) {
Timer.clear(autoOffTimer);
autoOffTimer = null;
}
}
}
});
// Monitor power consumption
Shelly.addStatusHandler(function(status) {
if (status.component === "switch:" + SWITCH_ID) {
if (status.delta.apower !== undefined) {
let power = status.delta.apower;
console.log("Power:", power, "W");
if (power > MAX_POWER) {
console.log("Power limit exceeded! Turning off.");
Shelly.call("Switch.Set", {id: SWITCH_ID, on: false});
Shelly.emitEvent("power_limit_exceeded", {
switch_id: SWITCH_ID,
power: power,
limit: MAX_POWER
});
}
}
}
});
Configuration Backup
// Backup all component configurations
function backupConfiguration() {
let backup = {
timestamp: Date.now(),
device: Shelly.getDeviceInfo(),
components: {}
};
// Backup common components
let componentTypes = ["sys", "wifi", "eth", "ble", "mqtt", "cloud", "switch", "input"];
for (let type of componentTypes) {
// Try single instance
let config = Shelly.getComponentConfig(type);
if (config) {
backup.components[type] = config;
}
// Try multiple instances (0-3)
for (let i = 0; i < 4; i++) {
let key = type + ":" + i;
config = Shelly.getComponentConfig(key);
if (config) {
backup.components[key] = config;
}
}
}
// Store backup (in chunks if needed due to storage limits)
let backupStr = JSON.stringify(backup);
console.log("Configuration backed up:", backupStr.length, "bytes");
// Store in script storage (if small enough)
if (backupStr.length < 1024) {
Script.storage.setItem("config_backup", backupStr);
console.log("Backup stored in script storage");
} else {
console.log("Backup too large for storage");
// Could send via HTTP POST to external server
}
return backup;
}
// Run backup
let backup = backupConfiguration();