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

[v1]Wireless Peripherals

Started by KingofGamesYami, 08 May 2014 - 11:39 PM
KingofGamesYami #1
Posted 09 May 2014 - 01:39 AM
This program was inspired by pocket computers. I thought, hey I have this tablet, but I can't use a monitor or a printer. The result was this api! It uses two programs, the api and a "slave" program.

The slave program is meant to be run on a normal computer with a wireless modem attached. It can be called with the api, and will also generate a spoof event. This means the program will generate events that happened to the slave on the master program. WARNING: This has not been tested with other programs that overwrite os.pullEventRaw! It takes 3 command line arguments:

wpslave <channela> <channelb> <modem_side>

The api is meant to be run on a (wireless) pocket computer, but it will also run just fine on a computer (if they wireless modem is placed on the back). It contains just two functions:

<variable> = wp.wrap(<side> <channela> <channelb>)
wp.setModem(<side>) --#note that by default, the modem is set on the back.  I have included this override if you wish to place the modem on a different side.

Note that if you want, you can wrap a peripheral on multiple slaves. For instance, you could have a computer for your door and a computer for your monitor, and be handling both with a third computer, or a (wireless) pocket computer.

wp

local modem = peripheral.wrap("back")

local oldos = {}
for k, v in pairs(os) do
	oldos[k] = v
end

function os.pullEventRaw(...)
	local args = {...}
	local event = {oldos.pullEventRaw(unpack(args))}
 	if event[1] == "modem_message" and type(event[5]) == "table" and event[5][1] == "wpe" then
  		return unpack(event[5][2])
	else
 		return unpack(event)
 	end
end

function setModem(side)
	modem = peripheral.wrap(side)
end

function wrap(side, channela, channelb)
	local per, call = {
	side = side,
	channela = channela,
	channelb = channelb,
}, {}
	modem.transmit(channela, channelb, side)
	modem.open(channela)
	msg = {os.pullEvent("modem_message")}
	for k, v in pairs(msg[5]) do
		call[v] = function(...)
			modem.transmit(channela, channelb, {side = side, call = v, params = {...}})
			return(unpack({os.pullEvent("modem_message")})[5])
		end
	end
	setmetatable(per, {__index = call})
	return per
end
wpslave

local args = {...}

if #args < 3 then
	error("Incomplete arguments", 2)
elseif #args > 3 then
	error("Too many arguments", 2)
end

assert(tonumber(args[1]), args[1].." isn't a number!")
assert(tonumber(args[2]), args[2].." isn't a number!")
args[1] = tonumber(args[1])
args[2] = tonumber(args[2])

local valid = false
for i = 1, 6 do
	if args[3] == (rs.getSides())[i] then
		valid = true
	end
end
if not valid then
	error("Side is not valid")
end

local modem = peripheral.wrap(args[3])
modem.open(args[2])

local function reply(info)
	modem.transmit(args[1], args[2], info)
end

while true do
	event = {os.pullEvent()}
	if event[1] == "modem_message" and type(event[5]) == "table" then
		local response = {peripheral.call(event[5].side, event[5].call, unpack(event[5].params))}
		reply(response)
		print("peripheral response sent")
	elseif event[1] == "modem_message" and type(event[5]) == "string" then
		local pm = peripheral.getMethods(event[5])
		reply(pm)
		print("peripheral table sent")
	else
		reply({"wpe", event})
		print("peripheral event sent")
	end
end

pastebin get TgHFHwkH slave
pastebin get eQkJhzG2 wp

Note: if you attempt to catch a peripheral event such as monitor_touch, the program will never return a value. If anyone knows how I could fix this, I would appreciate the help. Instead, use something similar to this code:

local event
while true do
 event = {os.pullEvent()}
 if event[1] == "monitor_touch" then
  break
 end
end
Edited on 09 May 2014 - 11:41 AM
skwerlman #2
Posted 09 May 2014 - 04:22 AM
Neat! But what if the slave gets a terminate event? Will that terminate the master?
awsmazinggenius #3
Posted 09 May 2014 - 04:45 AM
It seems that you override os.pullEventRaw to transmit events to the user. You can make custom events with os.queueEvent (search it up on the wiki), you know. I haven't looked at your code deeply, though, so I may be wrong.
CometWolf #4
Posted 09 May 2014 - 05:36 AM
He needs the override to catch the events in the first place, since they are originaly transmitted via rednet.
KingofGamesYami #5
Posted 09 May 2014 - 01:18 PM
Neat! But what if the slave gets a terminate event? Will that terminate the master?
No it won't. I might add that in the next release. The master will freeze up waiting for a reply most likely. (I also want to add an error timeout)

It seems that you override os.pullEventRaw to transmit events to the user. You can make custom events with os.queueEvent (search it up on the wiki), you know. I haven't looked at your code deeply, though, so I may be wrong.
He needs the override to catch the events in the first place, since they are originaly transmitted via rednet.
Correct, except they are transmitted via modem_message instead of rednet.
Edited on 09 May 2014 - 11:21 AM
CometWolf #6
Posted 09 May 2014 - 02:49 PM
When i say "rednet" im reffering to the actual method of transfer, not the event itself. I've always assumed the name for the connection between the computers is rednet, even though yes they are transmitted using modem_message events.
KingofGamesYami #7
Posted 10 May 2014 - 02:02 PM
When i say "rednet" im reffering to the actual method of transfer, not the event itself. I've always assumed the name for the connection between the computers is rednet, even though yes they are transmitted using modem_message events.
I always thought that rednet referred to the rednet api, whereas I am using the modem api to transmit my messages.
viluon #8
Posted 10 May 2014 - 02:38 PM
When i say "rednet" im reffering to the actual method of transfer, not the event itself. I've always assumed the name for the connection between the computers is rednet, even though yes they are transmitted using modem_message events.
I always thought that rednet referred to the rednet api, whereas I am using the modem api to transmit my messages.
-_-/> modem=rednet_modem CometWolf is right
skwerlman #9
Posted 10 May 2014 - 08:57 PM
CometWolf is indeed correct. The name goes back to a time before modems, when all data was passed through RedPower bundled cables.
[/offtopic]

Neat! But what if the slave gets a terminate event? Will that terminate the master?
No it won't. I might add that in the next release. The master will freeze up waiting for a reply most likely. (I also want to add an error timeout)
I was mostly wondering whether it was possible to remotely terminate a computer (via wireless modems; you can do it with wired ones).

Is there a limit to the number of masters a slave can have? What about slaves per master?

Finally, is it possible to have one computer be a slave and a master (i.e. receive events from a slave, echo them to its master)? (This'd be super useful for rednet repeaters)
KingofGamesYami #10
Posted 10 May 2014 - 10:36 PM
CometWolf is indeed correct. The name goes back to a time before modems, when all data was passed through RedPower bundled cables.
[/offtopic]

Neat! But what if the slave gets a terminate event? Will that terminate the master?
No it won't. I might add that in the next release. The master will freeze up waiting for a reply most likely. (I also want to add an error timeout)
I was mostly wondering whether it was possible to remotely terminate a computer (via wireless modems; you can do it with wired ones).

Is there a limit to the number of masters a slave can have? What about slaves per master?

Finally, is it possible to have one computer be a slave and a master (i.e. receive events from a slave, echo them to its master)? (This'd be super useful for rednet repeaters)
You could do it with some code, but not with mine… Terminate does not deal with peripherals, and therefor will not be used. In v1, key, char, and mouse_click events are mistakenly sent, working on a fix in v2… which is currently being debugged! Expect an update by wednesday :D/>

There is no limit on the number of masters controlling a slave, as all the masters listening on the correct channel will get the events. The downside is, if one master changes the background color on a monitor, the other master will be completely oblivious to this change.

Edit: There is a limit on the number of channels a modem can have open at one time: 128. However, I doubt anyone will run into this problem

On the subject of slaves:
If you do make multiple slaves, I would recommend using different channels for each one, as demonstrated below

os.loadAPI("wp")
local mon = wp.wrap("right", 2404, 2404)  --#these two values do not have to be the same, I just haven't gotten around to explaining them
local printer = wp.wrap("right", 2403, 2403)
mon.write("printing")  --#this seems a good time to point out that term.redirect(mon) *should* work with this.
printer.write("this is some text")
mon.write("printing complete")

It would be simple to create a repeater program:

modem = peripheral.wrap(side)
modem.open(channel) --#open as many channels as you like, before the loop.
while true do
 data = {os.pullEvent("modem_message")}
 modem.transmit(data[3], data[4], data[5])
end
No need to use either the api or the slave at all.
Edited on 10 May 2014 - 09:04 PM
Wojbie #11
Posted 10 May 2014 - 10:44 PM
It would be simple to create a repeater program:

modem = peripheral.wrap(side)
while true do
data = {os.pullEvent("modem_message")}
modem.transmit(channela, channelb, data[5])
end
No need to use either the api or the slave at all.

I see 2 problems :D/>

1. you did not open modem on any channel
2. Two or more of those repeaters in same range and you get nasty message looping if on same channels.
KingofGamesYami #12
Posted 10 May 2014 - 10:55 PM
It would be simple to create a repeater program:

modem = peripheral.wrap(side)
while true do
data = {os.pullEvent("modem_message")}
modem.transmit(channela, channelb, data[5])
end
No need to use either the api or the slave at all.

I see 2 problems :D/>/>

1. you did not open modem on any channel
2. Two or more of those repeaters in same range and you get nasty message looping if on same channels.
1. Fixed.
2. I have no idea how to fix this, aside from putting a sleep after it, causing it to miss events fired immediately after it. Why would you have two on the same channel anyway?
Wojbie #13
Posted 10 May 2014 - 11:08 PM
2. I have no idea how to fix this, aside from putting a sleep after it, causing it to miss events fired immediately after it. Why would you have two on the same channel anyway?

For long range systems :D/> so you know i get slave->repeater->repeater->master. 2 repeaters in middle would loop ;D
You can take a look at rednet repeater code if you want to see easy solution to this problem.
Its basically about storing last x messages (or messages send in last x seconds) and not repeating them. i think he also used some kind of semi-random identifier in each message if you are into stuff like that.

EDIT: You have inspired me to make my own version of your api :ph34r:/> With all the free time i have and all other CC stuff i code for fun it will be done in… 2-3 months :P/> Be ready for competition then!
Edited on 10 May 2014 - 09:09 PM
KingofGamesYami #14
Posted 11 May 2014 - 04:15 AM
2. I have no idea how to fix this, aside from putting a sleep after it, causing it to miss events fired immediately after it. Why would you have two on the same channel anyway?

For long range systems :D/> so you know i get slave->repeater->repeater->master. 2 repeaters in middle would loop ;D
You can take a look at rednet repeater code if you want to see easy solution to this problem.
Its basically about storing last x messages (or messages send in last x seconds) and not repeating them. i think he also used some kind of semi-random identifier in each message if you are into stuff like that.
In that case, I would simply resend the message on a different frequency or some such. The point I was originally trying to make was: Just make sure the modem_message gets through both ways and it will work.

EDIT: You have inspired me to make my own version of your api :ph34r:/> With all the free time i have and all other CC stuff i code for fun it will be done in… 2-3 months :P/> Be ready for competition then!
Hmm… you may not like the new features I'm adding :ph34r:/> hint: think about the letter "t" :ph34r:/>
Wojbie #15
Posted 11 May 2014 - 09:08 AM
Hmm you will allow hosting turtle or terminal table for remote control over computer screen/turtle movements? Sounds nice and would not require mutch code changes :ninja:
skwerlman #16
Posted 12 May 2014 - 06:31 AM
Hmm… you may not like the new features I'm adding :ph34r:/> hint: think about the letter "t" :ph34r:/>
TELEKINESIS?!?