147 posts
Location
My Computer
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
195 posts
Location
Cambridgeshire, England
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
147 posts
Location
My Computer
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
7083 posts
Location
Tasmania (AU)
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.
147 posts
Location
My Computer
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.
1281 posts
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
147 posts
Location
My Computer
Posted 22 January 2014 - 09:59 AM
I am going to consider this a dead thread. Can an admin please lock this?
52 posts
Location
Void
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.
147 posts
Location
My Computer
Posted 22 January 2014 - 02:30 PM
Is a rednet message modem_message? Or rednet_message?
172 posts
Location
United States
Posted 22 January 2014 - 03:55 PM
Here is everything you need to know on the rednet stuff…
http://computercraft.info/wiki/Rednet_(API)
286 posts
Location
United States
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
1281 posts
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
252 posts
Location
The Netherlands
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)
1852 posts
Location
Sweden
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
286 posts
Location
United States
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