PDA

View Full Version : TriggerEvent is asyncronous, queuing for later triggering...



salsbst
June 28th, 2003, 02:21 PM
TriggerEvent function in LUA let's you execute a command from within a LUA script.... sort of.

Actually, it isn't the Goto command at all. Instead, it puts the event into the queue for later processing. This tripped me up big time. I had a script that was processing a sequence of numbers that had to be sent to my cable box followed by the enter key (to change channels from SageTV).

I looped the sequence, and with each key, triggered the event/command in girder that sends the IR for the number to the cable box. in the loop, right after the IR transmission, I put TIME_Sleep function calls (available from WinLUAEx plugin) in order (I thought) to slow the loop down so that the box had time to process each IR transmission.

Boy was I wrong. The TIME_Sleep function calls were processed synchronously, while the TriggerEvent functions used to press buttons were both asynchronous and queued for execution after the script finished.

The net effect was that my script added up all of the miliseconds that had been sent to TIME_Sleep and did one major pause, then quickly ran through all of the events that had been triggered with TriggerEvent.

Bad news. Slower and just as unreliable as if I'd avoided TIME_Sleep altogether.

Solution: create a command (with an eventstring of "Global-Scripts-Wait") that has a VMS which calls TIME_Sleep with the pld1 as the argument. Then, in my channel changing script, substitute direct calls to TIME_Sleep with TriggerEvent("Global-Scripts-Wait", 18, 300);



-- channel change script
-- pld1 is the channel to change to on the cable box
-- cable-motorola-1 presses 1 on the cable box via IR
-- cable-motorola-2 presses 2 on the cable box via IR
-- etc.
l = strlen(pld1);
for i = 1,l-1 do
s = strsub(pld1,i,i)
TriggerEvent("cable-motorola-"..s,18);
TriggerEvent("Global-Scripts-Pause",18,500);
end
s = strsub(pld1,l,l)
TriggerEvent("cable-motorola-"..s,18);
TriggerEvent("Global-Scripts-Pause",18,200);
TriggerEvent("cable-motorola-enter",18);
TriggerEvent("Global-Scripts-Pause",18,300);
TriggerEvent("cable-motorola-exit",18);




--pauses for pld1 miliseconds
--tied to eventstring "Global-Scripts-Pause"
TIME_Sleep(pld1);


This way, the pauses are queued inline with the channel change IR commands, and I get the desired effect. Hope it helps someone.

Regards,
Stuart

mihooper
October 17th, 2003, 01:17 PM
Stuart,

Thanks for your excellent post. However.... :(

I have tried the technique you suggested (since I am struggling with exactly the same problem) but I continue to get all of my "TIME_Sleep" calls executed after all of the TriggerEvents have been executed. It's as if they are still being queued. At least, this is what Logger is showing.

Here is my lua command for the multi-character channel number:


--format of pld2 = "123xx,ABC.."
CommandString = (pld2)
--find length of Command String
CommandStrLen = strlen(CommandString)
--find length of Channel number
ChannelLen = (strfind(CommandString,",")-1)
--extract channel number
ChannelNumber = strsub(CommandString,1,ChannelLen)
--send each digit of channel number
for i = 1,ChannelLen do
ButtonNumber = format ("%1$1x", strsub (ChannelNumber,i,i))
if ButtonNumber=="00" then ButtonNumber="10" end
K={"SAT1","SAT2","SAT3","SAT4",
"SAT5","SAT6","SAT7","SAT8","SAT9","SAT0"}
BN=tonumber(ButtonNumber)
TriggerEvent(K[BN],18 )
TriggerEvent("Global-Scripts-Pause",18,200);
end


Do you see anything abviously wrong??

Here is what Logger shows


LUA: return main
LUA: return C TIME_Sleep global
LUA: call C TIME_Sleep global
LUA: return C LOGGER_String global
STRING: Pause=200
LUA: call C LOGGER_String global
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
LUA: return main
LUA: return C TIME_Sleep global
LUA: call C TIME_Sleep global
LUA: return C LOGGER_String global
STRING: Pause=200
LUA: call C LOGGER_String global
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
LUA: return main
LUA: return C TIME_Sleep global
LUA: call C TIME_Sleep global
LUA: return C LOGGER_String global
STRING: Pause=200
LUA: call C LOGGER_String global
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
EVENT: Dev: 18 SAT2
LUA: return main
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C tonumber global
LUA: call C tonumber global
LUA: return C format global
LUA: call C format global
LUA: return C strsub global
LUA: call C strsub global
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C tonumber global
LUA: call C tonumber global
LUA: return C format global
LUA: call C format global
LUA: return C strsub global
LUA: call C strsub global
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C TriggerEvent global
LUA: call C TriggerEvent global
LUA: return C tonumber global
LUA: call C tonumber global
LUA: return C format global
LUA: call C format global
LUA: return C strsub global
LUA: call C strsub global
LUA: return C strsub global
LUA: call C strsub global
LUA: return C strfind global
LUA: call C strfind global
LUA: return C strlen global
LUA: call C strlen global
LUA: call main
EVENT: Dev: 203 7.1 Pld1: 192.168.1.205 Pld2: 200,CNN
(note...bottom event is first event)

Sorry for the long post, but this is a 3 digit command with lots of calls. As you can see, all of the TIME_Sleep calls are queued at the end (top) of this log file.

Very confusing :-? Any suggestions would be appreciated.

Mark F
October 17th, 2003, 02:02 PM
Mike -

First, do you have the latest (http://prdownloads.sourceforge.net/girderplugins/Logger.1.0.6.zip?download) Logger plugin? It should be version 1.0.6. Your output looks like an earlier version. ;)

When ChannelNumber has a 0 in it, the value of ButtonNumber is not correct. Try this line to translate ButtonNumber instead of what you are currently using:


if ButtonNumber=="0" then ButtonNumber="10" end

mihooper
October 17th, 2003, 03:31 PM
Mar,

You're right. Somehow I digressed to 1.05. Here's essentially the same logfile using 1.06.....also, same results.



LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
EVENT: Dev: 18 SAT2
LUA: return main
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C strfind global
LUA: --> call C strfind global
LUA: --> return C strlen global
LUA: --> call C strlen global
LUA: call main
EVENT: Dev: 203 7.1 Pld1: 192.168.1.205 Pld2: 200,CNN
EVENT: Dev: 203 Accepted connection Pld1: 192.168.1.205
EVENT: Dev: 203 Incoming connection Pld1: 192.168.1.205


THanks for the tip on the number format. I'm still learning the formatting codes.... :wink:

Mark F
October 17th, 2003, 03:39 PM
When I changed you script the way I noted, it worked on my system. Hmmm.

Could you alter the script by adding some print statements to these lines?


ButtonNumber = format ("%1$1x", strsub (ChannelNumber,i,i))
if ButtonNumber=="0" then ButtonNumber="10" end
K={"SAT1","SAT2","SAT3","SAT4","SAT5","SAT6","SAT7","SAT8","SAT9","SAT0"}
BN=tonumber(ButtonNumber)
TriggerEvent(K[BN],18 )

Make it like this instead:


ButtonNumber = format ("%1$1x", strsub (ChannelNumber,i,i))
if ButtonNumber=="0" then ButtonNumber="10" end
K={"SAT1","SAT2","SAT3","SAT4","SAT5","SAT6","SAT7","SAT8","SAT9","SAT0"}
BN=tonumber(ButtonNumber)
print(ButtonNumber)
print(BN)
print(K[BN])
TriggerEvent(K[BN],18 )


The Logger output of this should tell the tale. :)

mihooper
October 17th, 2003, 04:00 PM
:oops: :oops: :oops:
Mark,

You are absolutely correct! I fixed the "00" problem and it DOES work! The thing that cofuses me is the fact that all of the TriggerEvents (C calls) are grouped at the end of the logfile, not in the middle of the original command.

Anyway, it works as expected.

Thanks again for your continued support!
:D



LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
EVENT: Dev: 18 SAT0
LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
EVENT: Dev: 18 SAT0
LUA: return main
LUA: --> return C TIME_Sleep global
LUA: --> call C TIME_Sleep global
LOGGING: Pause=200
LUA: call main
EVENT: Dev: 18 Global-Scripts-Pause Pld1: 200
EVENT: Dev: 18 SAT2
LUA: return main
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
PRINT: SAT0
PRINT: 10
PRINT: 10
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
PRINT: SAT0
PRINT: 10
PRINT: 10
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
LUA: --> return C TriggerEvent global
LUA: --> call C TriggerEvent global
PRINT: SAT2
PRINT: 2
PRINT: 2
LUA: --> return C tonumber global
LUA: --> call C tonumber global
LUA: --> return C format global
LUA: --> call C format global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C strsub global
LUA: --> call C strsub global
LUA: --> return C strfind global
LUA: --> call C strfind global
LUA: --> return C strlen global
LUA: --> call C strlen global
LUA: call main
EVENT: Dev: 203 7.1 Pld1: 192.168.1.205 Pld2: 200,CNN

Mark F
October 17th, 2003, 05:38 PM
Great! I'm glad it is working.


The thing that cofuses me is the fact that all of the TriggerEvents (C calls) are grouped at the end of the logfile, not in the middle of the original command.
This is working as designed and is the reason Stuart created this thread to begin with. :)

Each call to TriggerEvent() enqueues an eventstring. It does NOT cause Girder to execute the commands associated with the eventstring immediately. All of your script completes and then the enqueued events are processed, in order, like any incoming eventstrings.

One way to think about this is to consider a stack of blocks on your desk. New blocks (tasks) are always added to the very bottom and, when you complete the current block (task), you pull the next one from the very top.

TriggerEvent() adds a new task to the bottom of the stack while you are still working on the current task. When the current task (the script) is complete, the next task is taken from the top and so on until the stack is empty.

If it helps, this is commonly called a First-In-First-Out (FIFO) queuing strategy.

I feel like I'm babbling at this point so I'll stop. If this is still unclear, let me know and I'll try a different analogy.

pettan
November 19th, 2003, 05:14 AM
I've problems with my script, and the problem is that the TriggerEvent() does not get executed immediately, I need it to do that.

Anyone knows how to fix this?

Fixed it using check reg instead.

mostlyfodder
February 27th, 2004, 08:58 PM
regarding the first msg. in this thread, (posted a long time ago), does everyone use this method to create a delay between IR-Blaster numerical keypresses?

my IR Blaster (TIRA-2) is working great (although not w/ the newest version of Girder) but i can't figure out how to get Girder to pause to allow the set top digital cable box to receive all 3 digits of a channel change.

thanks,

fodder

fav front end:
http://www.myhtpc.net