StreamDeck Widget output being fetched by another Widget

On latest alfa 4.3.21
I created 2 simple JS widget buttons on my stream deck

(async () => {

  let result = await get_string_variable({ variable_name: 'my_var_name' })
  if (!result) {
    result = '{"text": "0", "BTTStreamDeckBackgroundColor": "100,100,100,255"}'
  }
  returnToBTT(result);
})();

The other one is supposed to have a blue bg (from the apparence/default tab) and it contains this code:

(async () => {
   returnToBTT('hello');
})()

They are both within a group.

When I open the group the second button will briefly display the blue background (not always), then switch to the bg set by the first widget (why?)

It sometimes correctly display "hello" but it will switch back and forth between "hello" and "0" that is the text set by the first button.
Sometimes it will start with 0 and switch back to "hello" and stay like this.

They both have checks "always run when widget becomes visible" and "execute script every" is set to big numbers for both (600).

So after banging my head against this for two days I've found out this problem goes away if I strip this line

my suspect is that there is a race condition.

While this part of the execution is on hold given the await, then the js engine goes ahead and run the next available function, that in this case might be the code of the second widget. That's quite normal in js land but then when it gets back to the context of the first function it propagates the result to the second one. And that's not normal.

I guess this problem seems to be related on how BTT has integrated the js engine.

In this particular case If I remove the await keyword the problems goes away

let result = get_string_variable({ variable_name: 'my_var_name' })

Ah sorry I wanted to look into this but forgot. I probably won't get to it until Monday, I'll post again once I have checked what's wrong.

2 Likes

Hello,
Any update on this?

1 Like

Hello and happy new year!

The bug still seem to exist, even in alpha channel :frowning:.

Any way we can help?

Thanks!

1 Like

Sorry, took me a bit to figure out what's happening. Will be fixed with the next alpha!

1 Like

I think the issue should be fixed in 4.367 alpha! (uploading now)

Hello @Andreas_Hegenberg, happy New year and thanks for the fix!
I'm downloading it now, you previously posted a temporary workaround, should we ignore it and use the standard returnToBTT?

I'll try to test this weekend

both approaches should now work fine (hopefully)

I'm still having similar issues with version 4.661: my javascript widgets are fetching each other's output. Actually it was never solved on my device. Any way I can help with more detail?

if possible create a non-working example and post it here, the examples I received all seemed to work fine after the fixes. Maybe I missed some detail

Here is one example, it connects to my local home assistant instance to retrieve the status of a sensor, then generate a json output based on the result:

async function sendCommand(url = '', theMethod = 'GET', data={}) {
    request= {    
      method: theMethod,
      cache: 'no-cache', 
      headers: {
        'Authorization': 'Bearer XXXXXXX',
        'Content-Type': 'application/json'
      }
    };
  if (!(JSON.stringify(data) === '{}')) {
      Object.assign(request, {'body': JSON.stringify(data)});
  }
  const response = await fetch(url, request);
  return response.json(); // parses JSON response into native JavaScript objects
}



(async() => {  
    response =  await(sendCommand('https://[local_homeassistant_instance]/api/states/input_select.papa_focus_mode'));
	switch (response.state){
	  case "available":
		  retour={ 
		    text: "X",
			BTTStreamDeckSFSymbolName: "person.crop.circle.badge.checkmark",
			BTTStreamDeckIconColor1 : "0,137,123",
			BTTStreamDeckIconColor2 : "61.235956, 122.250126, 252.081407, 255.000000",
		};	  
	    break;
	  case "do not disturb":
		  retour={ 
		    text: "X",
			BTTStreamDeckSFSymbolName: "person.crop.circle.fill.badge.xmark",
			BTTStreamDeckIconColor1 : "216,67,21,255",
			BTTStreamDeckIconColor2 : "123,38,15,255",
		};

	    break;
	  case "focus":	 
		  retour={ 
		    text: "X",
			BTTStreamDeckSFSymbolName: "person.crop.circle.badge.exclamationmark",
			BTTStreamDeckIconColor1 : "255,38,0",
			BTTStreamDeckIconColor2 : "255,147,0",

		};

	    break;
	  default:
	}
	

returnToBTT(JSON.stringify(retour));
}) ();

and here is another one, simpler, that seem to mess with it.


//0 ==> off
//1 ==> on

(async() => {    
    let litra_state = callBTT('get_number_variable', {variable_name: 'LitraState'});
	
	returnToBTT(await(litra_state));
}) ();

Here is what I get when the second one returns 0:

Capture d’écran 2024-08-14 à 15.37.21

Whereas the right icon is supposed to be like this:
Capture d’écran 2024-08-14 à 15.38.56

I've just started seeing this problem after updating to 4.669.
(Although it could have been happening earlier also, as I've had issues for a while related to Streamdeck+ touchscreen widgets not updating properly).

I added some logging to try and figure out what is going on using console.log().

Specifically I have a Streamdeck+ touchscreen widget that is an "Apple Script Widget". The widget script is Javascript. The widget has one "button down" action that is also Javascript. I added console.log messages to both scripts.

It appears to me that when I press the touchscreen widget, the button down action script for the widget is executed twice, and the return code from the first execution is being used to set the text on the widget. The Apple script widget is not executed at all. (I'm not sure if it should be or not)

What I expected was that the button down action script should be executed once, and the Apple script widget script should be executed either once or not at all, with the result of the Apple script widget script, if executed, used to set the widget text (and if executed, preferably after the button down script)

My widget script is set to update every 0 seconds. As I understand, this should result in it only getting called either when the button/touchscreen is pressed, or when update_widget is called from somewhere else.
At the moment, it does get called when update_widget() is called, but not when the touchscreen is pressed.

@telephant you are right. On the one hand v4.669 fixed an issue where the assigned script actions that are triggered when pressing the button did not update the widget correctly. However on the other hand it also added an issue where the assigned was executed twice.
This should now be fixed in 4.671!

@Andreas_Hegenberg ,

Thank you for the quick fix, that is an improvement!

However, I think there may still be a bug:

StreamdeckWidget_Bug_triggers.bttpreset (6.6 KB)

In the attached preset, there is a streamdeck config group with exactly one Apple Script widget. The (javascript) widget script for the widget both logs and returns the string "widget display", with a newline between the words so it shows up on the button better, and a random integer at the end so in a sequence of calls you can tell which was which.

When BTT starts up, the touchscreen button shows "widget display" as expected.

The (javascript) action script on button down does the same thing, but the string that is logged and returned is "widget press".

The behavior I expect is that the when the widget is pressed, the "on button down" script is called. This should generate a log message, but I do not expect that the return value from this call should affect the widget visual look.

When I press the widget, the string "widget press" is logged. This is expected. However, after this is pressed the streamdeck touchscreen button shows "widget press", indicating that the output of the widget "on button down" script has been used to update the widget. This is not expected behavior based on my reading of the docs and various messages on the forum.

Maybe I'm wrong and this is the expected behavior, if so, can you confirm that this is supposed to happen?

Thanks!

yes, this is indeed expected to make it easier to quickly update the widget state because the script assigned to a widget often changes what the widget should look like (e.g. a mute/unmute widget). If you return nothing from the action script, the widget should not change

@Andreas_Hegenberg ,

Thank you for the response. Using the result of the action script to update the widget makes a lot of sense.

I've run across two related cases that seem to have strange behavior that I want to ask you to look at, both in this preset:

StreamdeckWidget_Test2.bttpreset (21.2 KB)

Example 1:
Very similar to my previous test case. This is a streamdeck+ touchscreen widget with a widget display script and an action script.
Line 5 of the action script contains the line
let USE_TRIGGER = 1;
In this case the action script calls await trigger_named() to call a named trigger. The named trigger returns a value, and it is clear from the logging that the named trigger is being called successfully and returning the value. This value is used to compute the return value for the action script.

If I run this script from inside the BTT window by pressing the "Run Script" button, I get no output (but all the console logs are generated as expected). If I run it by pressing the widget, the console logs are generated, but the widget appearance does not change. This isn't what I expected based on your last comment.

If I change line 5 to let USE_TRIGGER = 0;
Then the named trigger doesn't get called, the console logs are generated, and the widget appearance changes to match the return value of the action script.

Summary: calling a named trigger in an action script seems to break the use of the action script return value to update the widget.

Example 2:
Another similar test case, here I've added a second action script to the widget.
Both action scripts compute a value, but neither returns anything (no return, no call to returnToBTT() ). I can run either script inside BTT by pressing the "Run Script" button. However, if I press the widget (I expected that both actions should run in sequence), then BTT reliably crashes.

Summary: calling two JS action scripts in sequence from a streamdeck widget seems to crash BTT.

Thanks!