Skip to main content


Since version 0.9.0

On this page you can find a short tutorial with an example scripting scenario to let you get started with Shelly scripts. Follow the steps to create your first script about idle alerts. The resulting script Script will monitor the inputs of a Shelly and if there was no user interaction with the input(s), it will call an URL with a predefined message.

More information about the scripting language can be found here. To know more about the Shelly's scripting API, click here.

Step 1: Enable debug over websocket#

To be able to easily receive results from the scripts we create and debug them, we will enable debulg logs (for example, for websocket) first. As described here and here, to do this, we will use:

Enable debug logs over websocket
export SHELLY= # IP of your device
curl -X POST -d '{"id":1, "src":"user_1", "method":"Sys.SetConfig", "params":{"config":{"debug":{"websocket":{"enable":true}}}}}' http://${SHELLY}/rpc

Then we will start receiving logs by executing the following command:

wscat ws://${SHELLY}/debug/log

Step 2: Create an empty script#

Create a script named my_idle_alert_script, using the method:

curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.Create", "params":{"name":"my_idle_alert_script"}}'\

The result from this method will be some id, let's say id=3.

Step 3: A simple script#

To start creating scripts, let's create some code that prints "Hello world!":

let greeting = "Hello world!";

To upload this code (chunk by chunk) to the script with id=3, which we previously created on the device, we can use:

curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.PutCode", "params":{"id":3,"code":"let greeting = \"Hello world!\";", "append": false}}'\
curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.PutCode", "params":{"id":3,"code":"print(greeting);", "append": true}}'\

Note that, when the code is long, we have to upload it chunk by chunk. In the example, it is uploaded line by line, but you may devide it differently across the invocations of Script.PutCode.

Another thing to note is that, as our first invocation of Script.PutCode contained the parameter "append":false, all of code uploaded previously in this Script object will be automatically removed and the content of the script will be replaced with the new code.

Alternatively (and much more simply) we can create the code in a file, let's say hello_world.txt and upload it in one step, using the script put_script. This script takes three parameters:

  • the IP of the device on which we will upload the script (already set as value of the env variable SHELLY)
  • the id of the script object, where we will upload the code (in our case id=3)
  • the name of the file containing the code itself ${SHELLY} 3 "hello_world.txt"

Step 4: Run your script#

Finally, we have the code uploaded and we can run our first Shelly script (the one with id=3):

curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.Start", "params":{"id":3}}'\

This must print 'Hello world!' in the debug log.

Step 5: Create an object in a script#

Now, we will start to create more sophisticated and useful scripts.

Firstly, let's create some variables: an object CONFIG and an alertTimer with value null:

let CONFIG = {
timeoutBeforAlert: 12 * 60 * 60 * 1000,
inputID: "", // string
inputEvent: -1, // int
alertEndpoint: "${message}"
let alertTimer = null;

Create a new script object using Script.Create, or just put new code to the previous Script object (the one with id=3) with Script.PutCode. Again, you can just use The resulting script (let's say, again with id=3) can be run as before, but it won't print anything to the terminal.

Step 6: Create a fuction that replaces strings#

Let's create a function called "replace". It will take three strings: origin, substr and replace, where substr is a substring of the origin. The function will replace substr with replace in origin.

function replace(origin, substr, replace) {
return origin.slice(0, origin.indexOf(substr)) + replace + origin.slice(origin.indexOf(substr) + substr.length, origin.length)

Add the function to the code from the previous step and upload it. The resulting script (let's say, again with id=3) can be run as before, but again, it won't print anything to the terminal. However, it can just be evaluated easily by the method:

curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.Eval", "params":{"id":3, "code":"replace(\"The first generation of Shelly devices rule the world!\", \"first\", \"second\")"}}'\

This must result in the string "The second generation of Shelly devices rule the world!".

Step 7: Create functions that start and stop a timer#

We will set a timer that fires repeatedly at every 12 hours, sending an http get request. If the response code from this request is 200, a message will be printed to notify about the success. The values used here are the ones we created in step 5.

function startTimer() {
alertTimer = Timer.set(CONFIG.timeoutBeforAlert,
function (ud) {
let alertURL = replace(CONFIG.alertEndpoint, "${message}", "Grandpa: No activity for 12 hours!");"HTTP.GET",
{ url: alertURL },
function (res, error_code, error_msg, ud) {
if (res.code === 200) {
print("Successfully transmitted a message");
function stopTimer() {

Again, append this code to the already added one.

Step 8: Add an event handler#

Let's add an event handler which will restart the timer when any event occurs. You will be notified about each reset timer by a message "TIMER WAS RESET" printed in the logs.

function (event, ud) {
// while we don't have better selectivity for event source
if (typeof ( !== 'undefined') {

Append this code to the already created one. Finally, we have the whole script and you can upload it.

Now, you can start the script.

If you have followed the steps properly, you will be notified each time when there was no event occurred in the last 12 hours (it may indicate a problem at home, or just the fact that someone is on a vacation :) ).

curl -X POST -d '{"id":1, "src":"user_1", "method":"Script.Start", "params":{"id":3}}'\