Jump to content
Shelly IoT Innovation Challenge started! ×

Example script - Virual components and Somfy TaHoma controller


Dimitar

Recommended Posts

This script show how to use components to control 3th party device. 

Also show how dynamically to change label and icon of the virtual components. 

 

image.thumb.png.63463bc69d5afbb44f6b8789b960ad79.png

 

let CONFIG = {
  token: "My token", // Replace with your actual token
  ip: "192.168.3.111:8443", // Replace with the IP of your TaHoma Hub
  hub: "io://1218-1660-0674/", // hubID
  encodedhub: "io%3A%2F%2F1218-1660-0674%2F"
};

let devices = [
  { url: "15077540", label: "Livingroom central", virtualComponentId: 200 },
  { url: "11848943", label: "Livingroom left", virtualComponentId: 201 },
  { url: "13858948", label: "Kitchen balcony", virtualComponentId: 202 }, 
  { url: "11743604", label: "Lower room left", virtualComponentId: 203 },
  { url: "14407349", label: "Lower room right", virtualComponentId: 204 },
  { url: "7827441", label: "Bassement left", virtualComponentId: 205 },
  { url: "13430515", label: "Bassement right", virtualComponentId: 206 }
  // Add more devices as needed
];

let checkInterval = 1000; // Adjust as needed for processing time
let currentDeviceIndex = 0;
let initializationDone = false;

function getDevices(device, isInitialization) {
  if (isInitialization === undefined) {
    isInitialization = false;
  }

  let url = "https://" + CONFIG.ip + "/enduser-mobile-web/1/enduserAPI/setup/devices/" + CONFIG.encodedhub + device.url + "/states";
  let payload = {
    method: "GET",
    ssl_ca: "*",
    headers: {
      "Authorization": "Bearer " + CONFIG.token
    },
    url: url
  };

  Shelly.call("HTTP.REQUEST", payload, function(res, err_code, err_msg) {
    if (err_code) {
      console.log("Error getting device state: ", err_msg);
      return;
    }

    try {
      let deviceData = JSON.parse(res.body);
      let openClosedState, closureState, nameState, movingState;

      for (let i = 0; i < deviceData.length; i++) {
        if (deviceData[i].name === "core:OpenClosedState") {
          openClosedState = deviceData[i].value;
        } else if (deviceData[i].name === "core:ClosureState") {
          closureState = deviceData[i].value;
        } else if (deviceData[i].name === "core:NameState") {
          nameState = deviceData[i].value;
        } else if (deviceData[i].name === "core:MovingState") {
          movingState = deviceData[i].value;
        }
      }

  console.log(device.virtualComponentId, " Device Name: ", nameState, " ", openClosedState, " ", closureState , " ", movingState ); 

       if (movingState === false) {
      Shelly.call("number.set", { id: device.virtualComponentId, value: closureState });
 //     icon(closureState, device.virtualComponentId);  
       }
       
      if (isInitialization) {
        device.lastScriptPosition = closureState; // Set initial script position     
        Shelly.call("number.set", { id: device.virtualComponentId, value: closureState });
      icon(closureState, device.virtualComponentId);  
      } else {
        if (movingState === false && device.wasMoving) {
 //         Shelly.call("number.setconfig", { id: device.virtualComponentId, config: { name: device.label } });
          icon(closureState, device.virtualComponentId);  
          device.wasMoving = false;
          device.lastScriptPosition = closureState; // Update last position set by the script
        } else if (movingState === true) {
          device.wasMoving = true;
//          Shelly.call("number.setconfig", { id: device.virtualComponentId, config: { name: device.label + " MOVING" } });
        }
          device.wasMoving = true;
 //         }         
      }
    } catch (e) {
      console.log("Error parsing response: ", e.message);
    }
  });
}

function sendSetPositionCommand(position, device) {
  let commandUrl = "https://" + CONFIG.ip + "/enduser-mobile-web/1/enduserAPI/exec/apply";
  let payload = {
    method: "POST",
    ssl_ca: "*",
    headers: {
      "Authorization": "Bearer " + CONFIG.token,
      "Content-Type": "application/json"
    },
    url: commandUrl,
    body: JSON.stringify({
      actions: [{
        deviceURL: CONFIG.hub + device.url,
        commands: [{
          name: "setClosure",
          parameters: [position]
        }]
      }]
    })
  };

  Shelly.call("HTTP.REQUEST", payload, function(res, err_code, err_msg) {
    if (err_code) {
      console.log("Error sending set position command: ", err_msg);
      return;
    }
    console.log("Set position command sent successfully: ", res.body);
    device.lastScriptPosition = position; // Update the last position set by the script
  });
}

function icon(state, device) {
    if (state == 100) { 
          iconurl = "http://minhome.net:8080/close.png"
        } else if (state == 0) {
          iconurl = "http://minhome.net:8080/open.png"
        } else { 
          iconurl = "http://minhome.net:8080/halfopen.png"
        }
        const currentConfig = Shelly.getComponentConfig("number:" + device);
        currentConfig.ui.icon = iconurl;
        Shelly.call("Number.setconfig",{ id: device, config: currentConfig});
      }
      
 
function processNextDevice() {
  if (currentDeviceIndex >= devices.length) {
    currentDeviceIndex = 0; // Reset index for regular monitoring
    if (!initializationDone) {
      // Initialization completed, now start regular checks
      initializationDone = true;
      Timer.set(checkInterval, true, processNextDevice); // Set regular interval
    }
    return; // Exit function to avoid further execution in this cycle
  }

  let device = devices[currentDeviceIndex++];
  getDevices(device, !initializationDone); // Pass true for initialization on first run

  if (!initializationDone) {
    // Use a shorter delay during initialization
    Timer.set(1000, false, processNextDevice);
  }
}

function initializeDevices() {
  currentDeviceIndex = 0;
  initializationDone = false;
  processNextDevice(); // Start the initialization process
}
Shelly.addStatusHandler(function(event) {
  if (event.component.indexOf("number:") === 0) {
    const componentId = parseInt(event.component.split(":")[1]);
    
    // Manually searching for the device in the array
    let device = null;
    for (let i = 0; i < devices.length; i++) {
      if (devices[i].virtualComponentId === componentId) {
        device = devices[i];
        break;
      }
    }

    if (device) {
      const newPosition = event.delta.value;
      sendSetPositionCommand(newPosition, device);
    }
  }
});

// Remove any additional Timer.set calls that are outside of your functions
initializeDevices(); // Only call this once to start the process

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...