Variable is not set by Custom Tile in other mobiles than mine

Hi Sharptools tribe, I would like for some help, about this issue:

  • I made a custom tile (supported by chatgpt) to handle a virtual device associated to an Air Conditioner by IFTTT (Midea Air applet). The connection works fine ST-IFFT-Air Conditioner.

  • The custom tile has 4 clicks, 1 for ON/OFF and 3 buttons for power off program (2h, 4h and 6h)

  • When a buttons for power off program is clicked it sends a value to a Sharptools variable, AATimer b.e. (2, 4 or 6 numeric values).

  • There is a rule that triggers when variable changes and start a cycle each hour to check if device is still on (if user did not power it off before the programmed time), subtracts 1 to variable until it gets a 0 value, then power off the device.

  • The custom tile works fine to ON-OFF the device

  • The custom tile works fine to Power Off program in my iPhone (buttons activates, and variable is set with correct value 2, 4 or 6), rule runs right, and device is powered off on time.

  • PROBLEM: When custom tile is inserted on my daughters mobiles dashboards the On/Off function works right, but when a button is clicked, it is activated on the custom tile, but the value is not set in the variable, variable stills on 0. Custom tile works fine setting the variable in my iPhone, but not set the variable in my daughters phones (one Android and other iPhone).

Checking in Chat GPT and recommends update chrome, delete cache, authorize java script, etc. I already done all recommendations but still the same. Also I double check correct variable is set on the custom tile.

I think this is the command is not working for my daughters Huawei.

if (acTimerVar) acTimerVar.setValue(hours);

Any idea? ..This is the seeting and code:

 {"type": "VARIABLE","name": "acTimerVar","label": "AC Timer Variable","filters": {"type": "Number"}}

And set the value:

function scheduleOff(hours, btn) {
  if (currentTimerButton) currentTimerButton.classList.remove(“on”);
  btn.classList.add(“on”);
  currentTimerButton = btn;
  if (acTimerVar) acTimerVar.setValue(hours); // <— AQUÍ SE ENVÍA EL VALOR A LA VARIABLE
}

This is the complete code if anyone wants to use it, I like it very much:

<!-- Tile Settings: permite seleccionar el dispositivo y la variable -->
<script type="application/json" id="tile-settings">
{
  "schema": "0.2.0",
  "settings": [
    {
      "type": "THING",
      "name": "acDevice",
      "label": "Select your AC device",
      "filters": {"capabilities": ["switch"]}
    },
    {
      "type": "VARIABLE",
      "name": "acTimerVar",
      "label": "AC Timer Variable",
      "filters": {"type": "Number"}
    }
  ],
  "name": "AA Control",
  "dimensions": {"height": 2, "width": 2}
}
</script>

<!-- SharpTools Library -->
<script src="https://cdn.sharptools.io/js/custom-tiles/0.2.1/stio.js"></script>

<!-- Estilos -->
<style>
  body { margin: 0; padding: 0; }
  .tile { 
    display: flex; 
    flex-direction: column; 
    align-items: center; 
    justify-content: center; 
    height: 100%; 
    background: #000000;
    border-radius: 8px;
    color: #ffffff;
    font-size: 0.75em;
  }
  .info { 
    margin: 2px; 
    font-size: 1.1em; 
  }
  .button { 
    margin: 2px; 
    padding: 4px 8px; 
    border-radius: 5px; 
    cursor: pointer; 
    background-color: #ccc; 
    color: #000; 
    font-size: 0.8em; 
  }
  .button.on { 
    background-color: #46CDFF; 
    color: #fff; 
  }
  .timer-buttons { 
    display: flex; 
    flex-direction: row; 
    margin-top: 4px; 
  }
  .icon-container {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .icon { 
    width: 50px; 
    height: 50px;
    transform: translateY(0px);
  }
</style>

<!-- HTML -->
<div class="tile">
  <div class="info" id="status">Loading...</div>
  <div class="icon-container">
    <img id="stateIcon" class="icon" src="" alt="State Icon">
  </div>
  <div class="timer-buttons" id="timerButtons">
    <div class="button" onclick="scheduleOff(2, this)">Off 2h</div>
    <div class="button" onclick="scheduleOff(4, this)">Off 4h</div>
    <div class="button" onclick="scheduleOff(6, this)">Off 6h</div>
  </div>
</div>

<!-- JavaScript -->
<script>
  let acDevice;
  let acTimerVar;
  let currentTimerButton = null;

  const ICON_ON = "https://firebasestorage.googleapis.com/v0/b/sharptools-default.appspot.com/o/users%2FaoR6XW3JjLcjzEGS0yy9BsJLMyV2%2Fuploads%2Ficons%2FAA%20On.gif?alt=media&token=28af3378-6e8b-4b9e-a91e-c3efdb3fab91";
  const ICON_OFF = "https://firebasestorage.googleapis.com/v0/b/sharptools-default.appspot.com/o/users%2FaoR6XW3JjLcjzEGS0yy9BsJLMyV2%2Fuploads%2Ficons%2FAA%20Off.png?alt=media&token=7717bfd1-8792-4e17-a484-38944019394e";

  stio.ready(data => {
    acDevice = data.settings.acDevice;
    acTimerVar = data.settings.acTimerVar;

    if (!acDevice || !acDevice.attributes["switch"]) {
      document.getElementById("status").innerText = "⚠️ Device or switch capability not found.";
      return;
    }

    // Listener para el cambio de estado ON/OFF
    acDevice.subscribe("switch");
    acDevice.attributes["switch"].onValue(val => {
      updateUI(val);
      if (val === "off") {
        clearTimerSelection();
        if (acTimerVar) acTimerVar.setValue(0);
      }
    });

    updateUI(acDevice.attributes["switch"].value);

    // AcciĂłn manual sobre Ă­cono
    document.getElementById("stateIcon").onclick = () => {
      const currentState = acDevice.attributes["switch"].value;
      const command = currentState === "on" ? "off" : "on";
      acDevice.sendCommand(command);
      if (command === "off") {
        clearTimerSelection();
        if (acTimerVar) acTimerVar.setValue(0);
      }
    };
  });

  function updateUI(state) {
    const statusDiv = document.getElementById("status");
    const stateIcon = document.getElementById("stateIcon");

    if (state === "on") {
      statusDiv.innerText = "AA ON";
      stateIcon.src = ICON_ON;
    } else {
      statusDiv.innerText = "AA OFF";
      stateIcon.src = ICON_OFF;
      clearTimerSelection();
    }
  }

  function scheduleOff(hours, btn) {
    if (currentTimerButton) currentTimerButton.classList.remove("on");
    btn.classList.add("on");
    currentTimerButton = btn;
    if (acTimerVar) acTimerVar.setValue(hours);
  }

  function clearTimerSelection() {
    if (currentTimerButton) {
      currentTimerButton.classList.remove("on");
      currentTimerButton = null;
    }
  }
</script>

If it’s not private / sensitive, do you think you could share the whole Custom Tile code? I’m wondering if I might be able to test it myself and see if I can reproduce or identify any issues.

I’m not seeing anything that sticks out to me as a major issue with the code snipper you shared.

I might be misremembering, but didn’t you say that tapping the variable on your daughter’s phone causes it to get highlighted but the variable value doesn’t actually change? If so, it sounds like the scheduleOff()is being called, but something about the acTimerVar final line isn’t working as expected.

Thanks Josh, making some simple custom tile test, I made (haha not me…ChatGpt) this simple custom tile to test if from my daughters mobile could set a value to a variable and same happened, The custom tile is just a button, when click on it sends a 5 value to the variable. In my iPhone works sharp, in my daughters, variable is bound, message that value was sent is displayed, but no value is set in the variable, in web and in my iphone works perfectly but in my daughter mobile it does not, I have not tested in my other daughter mobile yet..

<!-- SETTINGS: seleccionar variable numérica -->
<script type="application/json" id="tile-settings">
{
  "schema": "0.2.0",
  "name": "Test Var Write",
  "dimensions": { "height": 1, "width": 1 },
  "settings": [
    {
      "type": "VARIABLE",
      "name": "myVar",
      "label": "Selecciona la variable",
      "filters": { "type": "Number" }
    }
  ]
}
</script>

<!-- SharpTools lib -->
<script src="https://cdn.sharptools.io/js/custom-tiles/0.2.1/stio.js"></script>

<!-- Estilos: botĂłn grande rojo centrado -->
<style>
  html, body { height: 100%; margin: 0; }
  .wrap {
    height: 100%;
    display: flex; align-items: center; justify-content: center;
    background: #111; color: #fff; font-family: sans-serif;
  }
  #bigBtn {
    width: 92%; height: 88%;
    background: red; color: #fff;
    border: none; border-radius: 10px;
    font-size: 1.2em; cursor: pointer;
  }
  #bigBtn:active { background: #b30000; }
  #status { position:absolute; top:6px; left:8px; font-size: 0.8em; opacity: 0.8; }
</style>

<!-- HTML -->
<div class="wrap">
  <div id="status">Loading…</div>
  <button id="bigBtn" onclick="sendValue()">Enviar 5</button>
</div>

<!-- JS -->
<script>
  var myVar;

  stio.ready(function(data){
    myVar = data.settings.myVar;

    // Mensaje de estado inicial
    var statusEl = document.getElementById("status");
    if (!myVar) {
      statusEl.textContent = "⚠️ Selecciona la variable en Settings del tile";
    } else {
      statusEl.textContent = "âś“ Variable vinculada";
      // Opcional: suscripciĂłn para ver cambios en vivo (no requerido para la prueba)
      if (typeof myVar.subscribe === "function") {
        myVar.subscribe(function(val){
          // Muestra valor actual en el status (Ăştil para depurar)
          statusEl.textContent = "âś“ Variable vinculada (valor: " + val + ")";
        });
      }
    }
  });

  function sendValue() {
    var btn = document.getElementById("bigBtn");

    // Guardas contra “clics fantasma”
    if (!myVar) {
      alert("⚠️ Este tile no tiene variable vinculada.\nEdita el tile y selecciona la variable.");
      return;
    }
    if (typeof myVar.setValue !== "function") {
      alert("⚠️ La variable no admite setValue en este entorno.");
      return;
    }

    // Escritura
    myVar.setValue(5);

    // Feedback visual mĂ­nimo
    btn.style.transform = "scale(0.98)";
    setTimeout(function(){ btn.style.transform = ""; }, 120);

    // ConfirmaciĂłn
    alert("âś… Valor 5 enviado a la variable seleccionada");
  }
</script>

I might be misremembering, but didn’t you say that tapping the variable on your daughter’s phone causes it to get highlighted but the variable value doesn’t actually change? If so, it sounds like the scheduleOff()is being called, but something about the acTimerVar final line isn’t working as expected.

yes, Button is clicked as normal, but variable does not change its value, but in web does, in my iPhone does, but in my daughters phone does not.

Hey Carlos - just an update that I’ve been working on this for the past few days and have implemented two fixes:

  1. Sharing (server-side) - Variables were not being recognized for sharing when used within a Custom Tile, so unless you had used the Variable directly on a Dashboard somewhere else, it wouldn’t get shared properly
  2. Guest Variable Changes (frontend) - Guests weren’t being evaluated with the appropriate access levels when trying to change variable values through a Custom Tile

For the second part, the frontend changes, those are only released to beta at the moment. I’m heading to a concert this evening, so I didn’t want to risk rolling out the change to production right before that, but hopefully I’ll be able to get some better testing done in beta over the weekend and get it released by next week!

2 Likes

Just an update that the frontend changes are in production now.

If you already have the dashboard shared and you don’t have the Variable shared directly somewhere on the same dashboard or another dashboard with that particular guest, you will need to do one of the following so the guest will get the proper shared access to the variable:

  1. Unshare and reshare the dashboard with that guest (this requires them to accept the invite again).
  2. Remove all references to the variable through Custom Tiles on the impacted dashboard, save, then re-add them and save.
    (eg. removing all the Custom Tiles, save, then re-add the Custom Tiles and save)
  3. Share the impacted Variable directly with your guest – either on the impacted dashboard or on any other Shared Dashboard.

And the guest will need to refresh the page in their browser while they are viewing SharpTools to automatically pull in the latest updates.

2 Likes

Hi Josh, thanks for the solution, I will try and test, in the mid time I made a new custom tile (well chat gpt made it) to call a Sharptools rule and rule set the value to the variable, its working fine because avoids any variable sets and any variables permissions sharing problem, variables is set in the rule, inside the Sharptools environment. I will try your procedure and let you know. Thanks !

1 Like