This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
mrpoopy345's profile picture

Receiving rednet messages while in the shell

Started by mrpoopy345, 22 January 2014 - 06:34 AM
mrpoopy345 #1
Posted 22 January 2014 - 07:34 AM
Hello! I have a problem. I need a computer to receive rednet messages while able to interact with the shell.
This is my current code:

rednet.open("back")
[size=4]function receive()[/size]
id, message = rednet.receive()
print(message)
h = fs.open("temp", "w")
h.write(message)
h.close()
shell.run("temp")
end
local f = coroutine.create( receive )
coroutine.resume( f )
It doesn't do anything, even when you send it a rednet message.
Any help?
Edited on 22 January 2014 - 01:31 PM
6677 #2
Posted 22 January 2014 - 08:53 AM
why on earth are you calling your own program recursively, your just asking for trouble there with memory allocation
mrpoopy345 #3
Posted 22 January 2014 - 09:07 AM
? How am I calling my own program recursively? And can you give me some help to NOT call my program recursively? (Sorry if i'm acting stupid. I am new to coroutine's)
Edited on 22 January 2014 - 08:28 AM
Bomb Bloke #4
Posted 22 January 2014 - 09:10 AM
You aren't, best I can make out.

I'm not familiar enough with co-routines to speak of the actual results of this code, but it looks like the intention is to have the "receive()" function continue running once the script has ended, saving and then executing whatever code is messaged to the computer while the user does other things?

An off-the-top-of-my-head-assumption is that the function will terminate when the script does.
mrpoopy345 #5
Posted 22 January 2014 - 09:30 AM
You are correct bomb bloke. But can someone give me some code? I am new to coroutines, and need a little guidance here.
CometWolf #6
Posted 22 January 2014 - 09:57 AM
I have no experience running coroutines outside of the actual script that creates them, but my guess would be you'd have to atleast store them in _G(global enviroment). Also, note that a coroutine is considered "dead" after it's done exectuing, it will not loop unless the coroutine itself includes a loop. As such, yours will be dead after receiving one rednet message i believe, depending on what temp is.
Based on your code, im guessing what you wish to do is send code over rednet, and have the computer execute it. A better solution contrary to writing it to a file and then running it, would be to use loadstring. Which takes a string of code, reads it, and returns it as a function you may call. Using this and some loops, you could set it up to run the functions called over rednet as coroutines aswell.
Edited on 22 January 2014 - 09:02 AM
mrpoopy345 #7
Posted 22 January 2014 - 09:59 AM
I am going to consider this a dead thread. Can an admin please lock this?
CoLDarkness #8
Posted 22 January 2014 - 01:40 PM
I am going to consider this a dead thread. Can an admin please lock this?

Don't worry Mr. I'll help you right there.

For what you want, receiving rednet messages in shell and such.

You'll have to modify os.pullEvent & os.pullEventRaw with the following:

if it's a rednet message, make sure it does what you want AND returns the event & parameters of the os.pullEventRaw

if not, it returns the event & parameters of the os.pullEventRaw.

So basically, mod the os.pullEvents so that when it receives a rednet msg, it does what you want.
mrpoopy345 #9
Posted 22 January 2014 - 02:30 PM
Is a rednet message modem_message? Or rednet_message?
TechMasterGeneral #10
Posted 22 January 2014 - 03:55 PM
Here is everything you need to know on the rednet stuff…
http://computercraft.info/wiki/Rednet_(API)
surferpup #11
Posted 27 January 2014 - 01:36 AM
You'll have to modify os.pullEvent & os.pullEventRaw with the following:

So basically, mod the os.pullEvents so that when it receives a rednet msg, it does what you want.

Not exactly a great idea, rewriting os.pullEvent, and I am not sure it would work the way you have outlined. What about just creating a custom os that always runs and returns a parallel shell? I think I have seen a few posts on that. Maybe Lyqyd or some of the other advanced coders can give you some pointers on that.
Edited on 27 January 2014 - 12:37 AM
CometWolf #12
Posted 27 January 2014 - 03:20 AM
Rewriting pullEvent works just fine.
Here's how i do it.

oldPull = _G.os.pullEvent --original pullEvent
function modemControl(enable)
  if enable then
    if peripheral.getType"right" == "modem" then
      _G.modem = peripheral.wrap"right"
      modem.open(cTurtle.controlChannel)
    else
      return
    end
    _G.os.pullEvent = function(...) -- override original pullEvent
      local tEvent = {cTurtle.oldPull(...)}
      if tEvent[1] == "modem_message"
      and tEvent[3] == cTurtle.controlChannel then
        local oldRenderMove = _G.renderMove
        _G.renderMove = false
        local tArg = {}
        for word in tEvent[5]:gmatch"%S+" do --split message into words
          if word:match"^%d+$" then --convert numbers to number format
            word = tonumber(word)
          end
          table.insert(tArg,word)
        end
        local funcString = ""
        if tArg[1] == "shell" then
          table.remove(tArg,1)
          funcString = "shell.run('"
          for i=1,#tArg do
            if i > 1 then
              funcString = funcString.." "
            end
            funcString = funcString..tArg[i]
          end
          funcString = funcString.."')"
        elseif tArg[1] == "code" then
          table.remove(tArg,1)
          for i=1,#tArg do
            if i > 1 then
              funcString = funcString.." "
            end
            funcString = funcString..tArg[i]
          end
        else
          funcString = "cTurtle."..table.remove(tArg,1)..'(' --write function
          for i=1,#tArg do
            local arg = tArg[i]
            local dataType = type(arg) --determine type
            if i > 1 then
              funcString = funcString.."," --commas if multipe args
            end
            if dataType == "number" or arg == "true" or arg == "false" then --add numbers and booleans
              funcString = funcString..arg
            elseif dataType == "string" then --add strings
              funcString = funcString..'"'..arg..'"'
            end
          end
          funcString = funcString..")"
        end
        local func = loadstring("setfenv(1,_G) "..funcString) -- create function
        local tRes = {pcall(func)}
        local str = funcString.."\n"
        if tRes[1] then -- no errors
          table.remove(tRes,1) --remove error index
          for i=1,#tRes do --convert return values to string
            if tRes[i] == true then
              str = str.."True "
            elseif tRes[i] == false then
              str = str.."False "
            elseif type(tRes[i]) == "table" then
              for k,v in pairs(tRes[i]) do
                str = str..k.."="..v.." "
              end
            elseif tRes[i] then
              str = str..tRes[i].." "
            end
          end
        else --function failed
          str = str..tRes[2]
        end
        modem.transmit(cTurtle.responseChannel,cTurtle.controlChannel,str) --send return values
        _G.renderMove = oldRenderMove
      end
      return unpack(tEvent) -- return event params  
    end
  else
    _G.os.pullEvent = cTurtle.oldPullEvent --restore pullEvent
end
InputUsername #13
Posted 27 January 2014 - 08:47 AM
Here's how I would do it, without modifying os.pullEvent.

Warning: not tested. Also I have no idea whether this is a correct way of doing this.

local function receive()
  <receive code goes here>
end

local function runShell()
  shell.run(<insert location>) --I forgot what the location of the shell program is, but insert it here
end

parallel.waitForAny(receive,runShell)
TheOddByte #14
Posted 27 January 2014 - 09:14 AM
Hmm.. You could override os.pullEvent like this

--# Backup the original os.pullEvent
os_pullEvent = os_pullEvent or os.pullEvent
--# Override it
os.pullEvent = function( evt )
	local handle = { os_pullEvent( evt ) }
	if handle[1] == "rednet_message" then
		print("[Message Receieved]")
		print( "ID: " .. handle[2] .. "  Msg: " .. handle[3] )
	end
	return unpack( handle )
end

--# Restore the original function with this function
local function restore()
	os.pullEvent = os_pullEvent
end
NOTE: I haven't tested this, But it should work Here's a screenie for you
Edited on 27 January 2014 - 08:29 AM
surferpup #15
Posted 27 January 2014 - 03:48 PM
Rewriting pullEvent works just fine.
Hmm.. You could override os.pullEvent like this

Both far more experienced than I am … I defer to their judgment. I note they are restoring the original os.pullEvent() in their code. That was my big concern.

Thanks for the examples.
Edited on 27 January 2014 - 02:48 PM