Cuckoo clock using Homeyscript, an easy introduction to scripting

I just finished creating a cuckoo clock setup where the cuckoo sounds the same amount of times as the whole hour, just like the real deal. I am using Homey Script on my Homey Pro. It is an easy script I kept in a sequential form for easy reading. I’ll go through each section to explain a bit and leave the entire snippet at the end.

Prerequisites:

Steps

  1. Get the sound file (or any other you like) and upload it to your Soundboard.

  2. Open Homeyscript and create a new script. Start the script with a function that returns a value between 1 and 12 based on the current time. Finally, call the function in a variable to get the amount of times the cuckoo should sound. I should mention here that the script will probably fetch the UTC time, so based on your location in the world you should add or subtract hours from the let nextHour. (e.g. “let nextHour = now.getHours() +2”)

function getHour() {
    const now = new Date();
    let nextHour = now.getHours();
    
    // Reset to 0 when at midnight
    if (nextHour === 24) {
        nextHour = 0;
    }

    // Convert to 12 hour format
    nextHour = nextHour % 12;
    
    // Return 12 in case of zero
    if (nextHour === 0) {
        nextHour = 12;
    }

  return nextHour;
}

// Get value how many times the clock should ring
const ringTimes = getHour();
  1. Next create a function that will perform the actual sounding of the clock. This function starts a for loop that will iterate the same amount of times as the current whole hour stored in the variable ringTimes in the previous step.
    .
    The script starts with a try…catch block. This is optional, but makes for easier debugging so I left it here.
    .
    Next, we call Homey.flow.runFlowCardAction to perform a specific flow. At this point, the easiest way to get the specifics for the flow, I found, is to create a flow that has a flowcardaction that triggers the Soundboard to play on Sonos with the desired sound. Once you have this flow you can open Flows in your browser and use the browser’s Inspect functionality to catch the network traffic. This will show you exactly how the sound is created. This will include device-id’s (which I obfuscated here), sound-id’s and location, which can be hard to obtain otherwise. (if someone has an easier way, please let me know)
    .
    Finally, you can specify the volume to whatever you like, then add a little bit of waiting time. This time in milliseconds (1500 = 1,5second) should be longer than the duration of the mp3 you are playing, otherwise a new flow will already be triggered cutting off the old.
// For loop function to sound the clock ringTimes amount of times
async function ringCuckoo(ringTimes) {
  for (let i = 0; i < ringTimes; i++) {  // Gebruik i < ringTimes om de klok exact ringTimes keren te luiden
      try{
        await Homey.flow.runFlowCardAction({
        "id": "homey:device[uuid]:cloud_play_soundboard",
        "uri": "homey:flowcardaction:homey:device:[uuid]:cloud_play_soundboard",
        "args": {
          "sound": {
            "id": "f8d53295fb90ceaaf51b0c91",
            "type": "audio/mpeg",
            "name": "Cuculus canorus 1.mp3",
            "path": "userdata/f8d53295fb90ceaaf51b0c91.mp3"
          },
          "volume": 20
        },
        "group": "then"
      });
      await wait(1500);
    }
    catch (error) {
      console.error("Error while performing flowcard action:", error);
    }
  }
}
  1. And the last step in the script is to execute the ringCuckoo function with the argument ringTimes. This could be more concise, scripting wise, but this will keep the script clear and sequential to read.
// Sound the clock x amount of times
ringCuckoo(ringTimes);

The Flow
I will add screenshots later, but the Flow at this point is very basic. I start with the When “It is hour” to trigger the flow whenever the hour changes.

Then at the And, I specify the hour should be between 07:00 and 23:00. We don’t need to sound the cuckoo at night if we don’t want to.

Finally at Then select Homeyscript and execute the script you just generated and congratulations. You got yourself a 21st century Cuckoo clock!

Lessons learned
I found Homeyscript, while supporting Javascript does not work well with some async functions. This made for some challenges to get the script working.
.
I should change the time bit to automatically include my timezone. With the current setup, the clock will be off after a winter/summertime change.
.
This is fun!

I hope you enjoyed reading this. To finish off, below is the entire script.

The entire thing:

function getHour() {
    const now = new Date();
    let nextHour = now.getHours();
    
    // Reset to 0 when at midnight
    if (nextHour === 24) {
        nextHour = 0;
    }

    // Convert to 12 hour format
    nextHour = nextHour % 12;
    
    // Return 12 in case of zero
    if (nextHour === 0) {
        nextHour = 12;
    }

  return nextHour;
}

// Get value how many times the clock should ring
const ringTimes = getHour();


// For loop function to sound the clock ringTime amount of times
async function ringCuckoo(ringTimes) {
  for (let i = 0; i < ringTimes; i++) {  // Gebruik i < ringTimes om de klok exact ringTimes keren te luiden
      try{
        await Homey.flow.runFlowCardAction({
        "id": "homey:device[uuid]:cloud_play_soundboard",
        "uri": "homey:flowcardaction:homey:device:[uuid]:cloud_play_soundboard",
        "args": {
          "sound": {
            "id": "f8d53295fb90ceaaf51b0c91",
            "type": "audio/mpeg",
            "name": "Cuculus canorus 1.mp3",
            "path": "userdata/f8d53295fb90ceaaf51b0c91.mp3"
          },
          "volume": 20
        },
        "group": "then"
      });
      await wait(1500);
    }
    catch (error) {
      console.error("Error while performing flowcard action:", error);
    }
  }
}

// Sound the clock x amount of times
ringCuckoo(ringTimes);
3 Likes

Enjoyed reading this. Tip for right time always: const resA = await fetch(“https://worldtimeapi.org/api/ip”);

1 Like

Nice flow, but I greatly decreased the complexity for you:


you can make use of the fact that 0 is falsy in js

3 Likes

Nice improvement. A lot more concise. I should take a look at advanced flows too. :pray:

If you don’t want to use homeyscript at all:

It turns out that when you wanr one hour between steps you have to have 13 (!) steps in 12 hours.

1 Like