Jump to content




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


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

#41 Geforce Fan

  • Members
  • 846 posts
  • LocationMissouri, United States, America, Earth, Solar System, Milky Way, Universe 42B, Life Street, Multiverse, 4th Dimension

Posted 10 March 2015 - 02:08 AM

View PostPinkishu, on 17 June 2012 - 10:30 AM, said:

function os.pullEvent( _sFilter )
  local event, p1, p2, p3, p4, p5 = os.pullEventRaw( _sFilter )
  if event == "terminate" then
	print( "Terminated" )
	error()
  end
  return event, p1, p2, p3, p4, p5
end
Oh dear god, os.pullEvent() is programmed very poorly in that case.
It should be:
local event = {os.pullEventRaw( _sFilter )}
  if event[1] == "terminate" then
    error ( "Terminated" )
  end
  return unpack(event)
end
:\

Edited by Geforce Fan, 10 March 2015 - 02:09 AM.


#42 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 02:09 AM

Nope, even with that missing end added it still fails. After a few successful triggers the myTimer (ID 130 from previous example) stops triggering! Any ideas?

#43 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 10 March 2015 - 02:11 AM

FYI, when a timer completes and throws it's associated event, that's it - it stops, having completed its task. It doesn't automatically start counting again in preparation to throw another event, so there's no need to os.cancelTimer() it.

#44 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 02:19 AM

View PostBomb Bloke, on 10 March 2015 - 02:11 AM, said:

FYI, when a timer completes and throws it's associated event, that's it - it stops, having completed its task. It doesn't automatically start counting again in preparation to throw another event, so there's no need to os.cancelTimer() it.
So I should be setting up a new timer after each event to have it repeat?

E.G.

-- Do something every 5 seconds
local myTimer = os.startTimer(5)
while true do
  local event, p1, p2, p3, p4, p5 = os.pullEvent()
  if event == "timer" and p1 == myTimer then
	-- Do something
	myTimer = os.startTimer(5)
  end
  -- Process other events
end

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


#45 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 10 March 2015 - 02:22 AM

If you want it repeated, that's pretty much exactly how you'd do it.

But think about whether you'd want to "do something" first then restart the timer, or restart the timer first then "do something". Code execution takes time too.

#46 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 02:25 AM

Thank you for your quick replies :)

I will let you know if it works.

#47 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 02:47 AM

Only triggering twice! :wacko:

I added a counter in the display update function to show how many times the function is called. It gets called three times.

Here is the simplified code as it stands now...

local modem = peripheral.wrap("back")

local count = 1

modem.open(555)

term.clear()

local computerInRange = true

-- 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
				return false
			end
		end
		
		if e == "modem_message" and p2 == 555 then
			return p4
		end
	end
end

local function checkIn()
	local reply = transmit(1, "Hello?")
	if reply == false then
		computerInRange = false
		return true
	elseif reply == "Hi!" then
		return true
	end
	return false
end

local function updateDisplay()
	term.setCursorPos(1,1)
	term.write(tostring(count))
	count = count + 1
end

updateDisplay()

while true do
	local myTimer = os.startTimer(2)
	local event, p1, p2, p3, p4, p5 = os.pullEvent()
	
	if event == "timer" then
		if p1 == myTimer then
			updateDisplay()
			if checkIn() == false then break end
		end
	end

	-- Other events
end


PS I am a seasoned ex-programmer. I had over 10 years professional C/C++ programming before I was forced to quit for family reasons ;)


EDIT - I ran the above code as a test program and the timer was triggered 3 times (the updateDisplay was called 4 times) then stopped!
I adjusted the value from 2 seconds to 4 seconds and it works fine!

Edited by Galbi3000, 10 March 2015 - 03:06 AM.


#48 Galbi3000

  • Members
  • 22 posts

Posted 10 March 2015 - 03:19 AM

Ok, final post. I have solved the problem! Even though that simplified version worked with a longer pause my main program still failed after 2 triggers!

The reason was the transmit timeout timer! If the target computer responds fine, the function returned but that timer was still active. For some reason, when it triggered, it stopped the main timer from working!

To solve it I put back the os.cancelTimer() call in one place...

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
				return false
			end
		end
		
		if e == "modem_message" and p2 == 555 then
			os.cancelTimer(timeout)
			return p4
		end
	end
end

Now my program works fine, even with the main timer value set to 1 second :)

Edited by Galbi3000, 10 March 2015 - 03:20 AM.


#49 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 10 March 2015 - 04:40 AM

View PostGalbi3000, on 10 March 2015 - 03:19 AM, said:

For some reason, when it triggered, it stopped the main timer from working!

In your main program loop down the bottom of the script, you create a new timer and store the id in "myTimer" whenever any event occurs (eg, transmit()'s timer expires, the user presses a key, a modem_message event happens, etc...). You should only be recreating that timer when it expires, because the old timers that you aren't bothering to catch as a result of all this are themselves leading to new timers being created, and so on...

#50 DaKillerBear1

  • Members
  • 21 posts

Posted 16 May 2015 - 01:04 PM

I have a problem, how can I make it so that if there is no key being pressed at the moment the program just continues?

#51 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 16 May 2015 - 02:57 PM

View PostDaKillerBear1, on 16 May 2015 - 01:04 PM, said:

I have a problem, how can I make it so that if there is no key being pressed at the moment the program just continues?
queue a timer with 0 seconds before you pull events

--# start a timer that will complete immediately
local timeout = os.startTimer(0)

--# get the next event in the queue
local event = { os.pullEvent() }

--# check if the event was a keypress, otherwise ignore the event
if event[1] == "key" then
  -- do stuff
end


#52 Waitdev_

  • Members
  • 432 posts
  • LocationAdelaide

Posted 17 May 2015 - 09:24 AM

i know a lot about os.pullevent and i was looking for even more ways to use it, but really nice how you made something to teach others. now even i have a reference if i forget anything :)





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users