Jump to content




os.pullEvent(): What is it and how is it useful?


  • You cannot reply to this topic
51 replies to this topic

#21 Explorer

  • New Members
  • 3 posts

Posted 18 July 2012 - 06:14 AM

Thanks this really cleared my syntax confusion in a few of my programs

#22 NeverCast

  • Members
  • 400 posts
  • LocationChristchurch, New Zealand

Posted 29 August 2012 - 11:51 PM

I know this is an old topic, but I feel this should be asked and why not on a forum post that is referenced from the wiki where others can see it.

If I filter an event with a string parameter to either pullEvent or pullEventRaw, will any event at the top of the stack/head of the queue ( However the events are implemented ) be destroyed if it does not match. What I mean is, if I use os.pullEvent("rednet_message"), press a key, then receive a message. Will that key press still be in the queue waiting for either a pullEvent("char"), pullEvent("key") or pullEvent(). OR will it be disposed and gone?

The reason I ask is if I'm waiting for a redstone signal, will rednet messages still be queued up. I know I could use a while loop without a filter. But it'd be good to know how filters handle non-matching events. If anyone can answer this it would be greatly appreciated.

Thanks, and sorry for the grave dig.

- NC

#23 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 30 August 2012 - 12:59 AM

View PostNeverCast, on 29 August 2012 - 11:51 PM, said:

I know this is an old topic, but I feel this should be asked and why not on a forum post that is referenced from the wiki where others can see it.

If I filter an event with a string parameter to either pullEvent or pullEventRaw, will any event at the top of the stack/head of the queue ( However the events are implemented ) be destroyed if it does not match. What I mean is, if I use os.pullEvent("rednet_message"), press a key, then receive a message. Will that key press still be in the queue waiting for either a pullEvent("char"), pullEvent("key") or pullEvent(). OR will it be disposed and gone?

The reason I ask is if I'm waiting for a redstone signal, will rednet messages still be queued up. I know I could use a while loop without a filter. But it'd be good to know how filters handle non-matching events. If anyone can answer this it would be greatly appreciated.

Thanks, and sorry for the grave dig.

- NC
They are removed from the queue, and then checked for the filter. So yes, they are deleted and lost. You should make a while loop like you said, or use parallel and wait for different events in each function. Is basically the same, but depending what you want to do one will be better thatn the other.

#24 timothyhtime

  • New Members
  • 1 posts

Posted 20 September 2012 - 05:54 PM

I'm trying to recode the terminate event, but I don't want it to interfere with my program running. Is there a way to reprogram the terminate event without stalling the program with a pullEvent. maybe just a way to check if an event is present or what, I don't know, but some direction here would help. thanks.

EDIT: ok, so I've found a way to get around it, but what I'm looking for at this point is a way to check two events and ignore any other event. any suggestions?

EDIT2: well, I managed to come up with a less than desired, but fully functional (as far as I can tell) solution to my problem. for those of you who are interested in being able to do the same. here you go.

os.pullEvent = os.pullEventRaw
function termiFunc()
  -- your alternative terminate commands
  print("bye")
  sleep(3)
  os.shutdown()
end
function checkEvent()
  local e = os.pullEvent()
  if (e == "terminate") then
	termiFunc()
  elseif not (e == "timer") then
	checkEvent()
  end
end
for a = 0, 20 do
  os.startTimer(.5)
  checkEvent()
  print("next")
end


#25 Noodle

  • Members
  • 989 posts
  • LocationSometime.

Posted 20 September 2012 - 10:22 PM

View Posttimothyhtime, on 20 September 2012 - 05:54 PM, said:

I'm trying to recode the terminate event, but I don't want it to interfere with my program running. Is there a way to reprogram the terminate event without stalling the program with a pullEvent. maybe just a way to check if an event is present or what, I don't know, but some direction here would help. thanks.

EDIT: ok, so I've found a way to get around it, but what I'm looking for at this point is a way to check two events and ignore any other event. any suggestions?

EDIT2: well, I managed to come up with a less than desired, but fully functional (as far as I can tell) solution to my problem. for those of you who are interested in being able to do the same. here you go.

os.pullEvent = os.pullEventRaw
function termiFunc()
  -- your alternative terminate commands
  print("bye")
  sleep(3)
  os.shutdown()
end
function checkEvent()
  local e = os.pullEvent()
  if (e == "terminate") then
	termiFunc()
  elseif not (e == "timer") then
	checkEvent()
  end
end
for a = 0, 20 do
  os.startTimer(.5)
  checkEvent()
  print("next")
end
Nice code for a newbie!
A few things though
1: os.pullEvent = os.pullEventRaw protects from termination, no real use in this script.
2: 'While true do' is a better kind of loop.
Helpful code
while true do
 e = os.pullEvent()
 if e == "terminate" then
   termiFunc()
 end
end
That will loop repeatedly, no need for the checkEvent().

#26 Cranium

    Ninja Scripter

  • Moderators
  • 4,031 posts
  • LocationLincoln, Nebraska

Posted 20 September 2012 - 10:26 PM

Calling a function within the function is a bad practice. That will cause an overflow error, because of recursion. Noodle is right, a while loop is better.

#27 Zambonie

  • Members
  • 477 posts
  • LocationSpring Hill, Fl

Posted 28 December 2012 - 09:45 AM

To me,its like an more advanced way of saying:

local input = read()
if input == "1" then

Altleast I learned it....

#28 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 28 December 2012 - 01:34 PM

View PostOnionnion, on 30 April 2012 - 02:15 AM, said:

  • "char" when text is typed on the keyboard. Argument is the letter typed.
  • "key" when a key is pressed on the keyboard. Argument is the numerical keycode.
  • "timer" when a timeout started by os.startTimer() completes. Argument is the value returned by startTimer().
  • "alarm" when a time passed to os.setAlarm() is reached. Argument is the value returned by setAlarm().
  • "redstone" when the state of any of the redstone inputs change.
  • "disk" or "disk_eject" when a disk is entered or removed from an adjacent disk drive. Argument is the side.
  • "rednet_message" when a message is received from the rednet API.


You missed 8...

http://www.computerc...ent#Event_Types

#29 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 28 December 2012 - 02:03 PM

View PostTheOriginalBIT, on 28 December 2012 - 01:34 PM, said:

View PostOnionnion, on 30 April 2012 - 02:15 AM, said:

  • "char" when text is typed on the keyboard. Argument is the letter typed.
  • "key" when a key is pressed on the keyboard. Argument is the numerical keycode.
  • "timer" when a timeout started by os.startTimer() completes. Argument is the value returned by startTimer().
  • "alarm" when a time passed to os.setAlarm() is reached. Argument is the value returned by setAlarm().
  • "redstone" when the state of any of the redstone inputs change.
  • "disk" or "disk_eject" when a disk is entered or removed from an adjacent disk drive. Argument is the side.
  • "rednet_message" when a message is received from the rednet API.


You missed 8...

http://www.computerc...ent#Event_Types
It should say "the most common events" then.

terminate is invisible to most programs as it's handled inside os.pullEvent.
Same for http_success and http_failure which are handled inside http.get.
peripheral and peripheral_detach should probably be included.
mouse_click, mouse_scroll and mouse_drag were added after the post was written.

#30 Zudo

  • Members
  • 800 posts
  • LocationUK

Posted 03 July 2013 - 12:34 PM

// Off topic

How did you get that title?

#31 Bordo_Bereli51

  • Members
  • 9 posts

Posted 04 July 2013 - 01:10 PM

A very good guide to understand. Thank you!

#32 RichyRocker423

  • Members
  • 3 posts

Posted 17 July 2013 - 11:14 PM

Is there a way to have os.pullevent look for 2 events? Like I'm trying for monitor touch and redstone, so that they will both end the waiting period os.pullevent induces. If I have to I'll set all the other types off but I don't know how. Please respond soon.

#33 LBPHacker

  • Members
  • 766 posts
  • LocationBudapest, Hungary

Posted 18 July 2013 - 01:25 AM

View PostRichyRocker423, on 17 July 2013 - 11:14 PM, said:

-snip-
No way of making os.pullEvent listen to more than one events. You'll have to check the event yourself.
while true do
    -- * puts everything returned by .pullEvent into a table
    local eventData = {os.pullEvent()}
    -- * eventData[1] will contain the name of the event
    if eventData[1] == "monitor_touch" then
        -- * do something with the other indexes of eventData
        -- * unocomment the block below if you have no idea what to do with eventData

        --[[ local side = eventData[2]
        local touchX = eventData[3]
        local touchY = eventData[4]
        -- * now you have side, touchX and touchY
        ]]

        -- * ...
    elseif eventData[1] == "redstone" then
        -- * ...
    end
end
See? It'll check the first parameter returned by .pullEvent, and that contains the name of the event. This:
-- * ...
means that you have to insert your code there.

#34 CyborgAlex

  • Members
  • 9 posts

Posted 30 July 2013 - 12:03 PM

Thanks For help

#35 Eunomiac

  • New Members
  • 2 posts

Posted 11 August 2013 - 02:08 PM

One of the problems I have with using events is that, once you tell the program to listen for an event, it has to stop in its tracks until the event occurs. Is there a way to get a program to listen for an event, but continue what it's doing until the event is triggered? I.e. "Keep doing what you're doing until you receive a 'stop' message over rednet. When you do, no matter where you are in the program, break and immediately do [X]." (A specific example might be an emergency RedNet kill switch for a lengthy 'while true do ... end' loop, or an alarm event that you want to break/terminate your program at the instant the alarm fires.)

Should I look for answers in the "parallel" API, using alternating yields to manage the coroutines? Or is there a better/cleaner way to go about this?

#36 LBPHacker

  • Members
  • 766 posts
  • LocationBudapest, Hungary

Posted 11 August 2013 - 03:38 PM

View PostEunomiac, on 11 August 2013 - 02:08 PM, said:

-snip-
Yup, using coroutines in that case is possible (or a rednet.receive with a short timeout at the beginning of the endless loop - most of those things can be solved without using coroutines though). BUT:

View PostEunomiac, on 11 August 2013 - 02:08 PM, said:

no matter where you are in the program
Even with coroutines, only one piece of code runs at a time. In order to eg. check for messages over rednet, the program (or the coroutine) which has to stop on a "kill" message must yield - that is, call os.pullEvent and the like.

#37 Onionnion

    Lua Teacher

  • Members
  • 27 posts

Posted 24 November 2013 - 05:18 PM

Discussion on this still going on through August? Neat. If any of this is out of date let me know, I shall fix if needed. I've been away, yes, but I'm taking some dips back here.

#38 Fedkiv

  • New Members
  • 2 posts

Posted 07 December 2013 - 07:39 AM

Ive been reading about mission building and I see a lot of references to "Flags".

From what I understand they are a true false condition that can trigger other events.

What I dont understand is how to add one in the mission editor. Nothing I can find says "add flag" or anything like that.

Im sure it is a simple procedure but I cant seem to figure it out.

Thanks

#39 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 01:43 AM

I know this is an old thread but I am having difficulty with os.pullEvent()!

I set a timer to activate every 2 seconds. Let's say that gets given an ID of 130.
I then start a communication function to communicate with a target computer. That function sets another timeout timer of 4 seconds. Let's say that gets the ID of 131.

The loop for the communication function receives the pullEvent trigger for timer 130, ignores that as it should, then another 2 seconds later gets the pullEvent trigger for timer 131. The function calls os.cancelTimer(131) after the correct ID was found on the timer event, also calls that if the function gets the response message before that timer is triggered.

The communication function works fine, does what is expected every time.

The problem occurs in the main program loop. It does a pullEvent to test for keyboard input and that 2 second timer (ID 130 in this example). It gets the key events but never gets the timer event!

Here is the code with unimportant parts taken out...

local modem = peripheral.wrap("back")
modem.open(555)
local count = 0
term.clear()
local computerInRange = true
local myTimer = os.startTimer(1)

-- Function transmit
--
-- Transmits a message and gets a response.
-- If no response in 4 seconds, returns false.
local function transmit(port, message)
  modem.transmit(port, 555, message)
  local timeout = os.startTimer(4)

  while true do
    local e, p1, p2, p3, p4, p5 = os.pullEvent()

    if e == "timer" then
	  if p1 == timeout then
	    os.cancelTimer(timeout)
	    return false
	  end
    end

    if e == "modem_message" and p2 == 555 then
	  os.cancelTimer(timeout)
	  return p4
    end
  end
end

local function updateDisplay()
  -- Updates the status display
end

-- First gets status data then continues:

updateDisplay()
while true do
  local event, p1, p2, p3, p4, p5 = os.pullEvent()

  if event == "timer" then
    if p1 == myTimer then
	  -- Update display
	  updateDisplay()
	  -- Poll for other computer
	  reply = transmit(123, "Hello?")
	  if reply == false then
	    computerInRange = false
	  elseif reply == "Hi!" then
	    computerInRange = true
	  else
	    term.clear()
	    print("Unexpected response!")
	    print("Checking in.")
	    print("Remote computer: "..reply)
	    break
	  end
    end

    if event == "key" and p1 == 38 then
	  -- Do key L event stuff
    end

    if event == "key" and p1 == 24 then
	  -- Do key O event stuff
    end
end

os.cancelTimer(myTimer)

It is run on a portable computer which is why it needs to check if the target computer is in range while also updating the display.

Edited by Galbi3000, 10 March 2015 - 01:54 AM.


#40 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 01:58 AM

Never mind, I have seen my mistake after going through the simplified code to tidy it in the posting! lol

It's a missing 'end' statement that ComputerCraft scripting missed! No errors given for the missing end! :P

Edited by Galbi3000, 10 March 2015 - 02:00 AM.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users