Skip to main content
Version: 1.0

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

PropertyTypeDescription

method

string

Name of the RPC method to invoke

params

object or null

Parameters for the method

callback

function

Optional callback function

PropertyTypeDescription

result

any

Result from the RPC call (null if no data, undefined on error)

error_code

number

0 on success, non-zero on error

error_message

string

Error description if error occurred

userdata

any

The userdata passed to the call

userdata

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

PropertyTypeDescription

callback

function

Function called when event occurs

PropertyTypeDescription

event_data

object

Event information object

userdata

any

The userdata passed during subscription

userdata

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

PropertyTypeDescription

name

string

Name of the custom event

data

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

PropertyTypeDescription

type_or_key

string

Component type (e.g., "switch") or full key (e.g., "switch:0")

id

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

PropertyTypeDescription

type_or_key

string

Component type (e.g., "switch") or full key (e.g., "switch:0")

id

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 ID
  • model - Device model
  • mac - MAC address
  • fw_id - Firmware version
  • app - 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();