Jump to content




[1.5+] In-depth Modem Channels Tutorial

wireless networking peripheral

69 replies to this topic

#41 Bubba

    Use Code Tags!

  • Moderators
  • 1,142 posts
  • LocationRHIT

Posted 18 February 2013 - 09:34 AM

View PostLDShadowLord, on 18 February 2013 - 09:02 AM, said:

Question, when I use the code provided in this tutorial I get some extra info which I'm not sure on.
Here is an example.

Quote

modem_message --Event Triggered
top --Where the modem is
number1 --send channel
number2 --reply channel
message --Standard message
number3 --?????
What is the number 3 which always appears at the bottom?, it's really frustrating me.

EDIT: Did some more testing, it appears to be quite random?

That is the distance between the computers :)

#42 LDShadowLord

  • Members
  • 115 posts

Posted 18 February 2013 - 11:12 AM

View PostBubba, on 18 February 2013 - 09:34 AM, said:

View PostLDShadowLord, on 18 February 2013 - 09:02 AM, said:

Question, when I use the code provided in this tutorial I get some extra info which I'm not sure on.
Here is an example.

Quote

modem_message --Event Triggered
top --Where the modem is
number1 --send channel
number2 --reply channel
message --Standard message
number3 --?????
What is the number 3 which always appears at the bottom?, it's really frustrating me.

EDIT: Did some more testing, it appears to be quite random?

That is the distance between the computers :)
Aha! Gotcha, thankyou!

#43 DarkWasp

  • New Members
  • 2 posts

Posted 21 February 2013 - 06:53 PM

What is the most efficient way to weed out all of the information other than the message itself?

Aside from a bit of coding I did over a decade ago, my programming experience is about 2 days old now so I still get caught up on the basics from time to time.

Basically what I've got is:

local modem = peripheral.wrap("top")

modem.open(127)

local messageArguments = {os.pullEvent("modem_message")}

table.remove(messageArguments) -- Remove distance
table.remove(messageArguments, 1) 
table.remove(messageArguments, 1)
table.remove(messageArguments, 1)
table.remove(messageArguments, 1) -- Remove everything up until the message itself
  
for i,rawmessage in pairs(messageArguments) do
 
  message = rawmessage
  
print(message)

end

I'm sure it's highly inefficient and I'm curious to know what the best and shortest way to do this. All I want to do is pull only the message out into a variable and leave the rest of the information behind.

#44 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 21 February 2013 - 07:01 PM

View PostDarkWasp, on 21 February 2013 - 06:53 PM, said:

What is the most efficient way to weed out all of the information other than the message itself?

- snip -
A table can be accessed by indexes or keys, so you can do this to extract the message and still preserve all the other data, which you will most likely need later.
local modem = peripheral.wrap("top")
modem.open(127)
local messageArguments = {os.pullEvent("modem_message")}
local message = messageArguments[5]
print(message)

have a read of this and this

Edited by TheOriginalBIT, 21 February 2013 - 07:02 PM.


#45 DarkWasp

  • New Members
  • 2 posts

Posted 21 February 2013 - 07:56 PM

View PostTheOriginalBIT, on 21 February 2013 - 07:01 PM, said:

View PostDarkWasp, on 21 February 2013 - 06:53 PM, said:

What is the most efficient way to weed out all of the information other than the message itself?

- snip -
A table can be accessed by indexes or keys, so you can do this to extract the message and still preserve all the other data, which you will most likely need later.
local modem = peripheral.wrap("top")
modem.open(127)
local messageArguments = {os.pullEvent("modem_message")}
local message = messageArguments[5]
print(message)

have a read of this and this

Ah, thanks that helps a lot. So much makes more sense now.

Actually this channel feature could not have come at a better time for me.

A friend made a redpower 2 frame elevator for me controlled by GPS, but he hasn't been on since Mindcrack updated CC to 1.5 and much of his rednet code started failing. So far I've been able to learn enough (mostly just by looking through his programs) to debug nearly all of the issues and get the elevator running again. However, I kind of got addicted and decided to vastly improve his elevator call button computers(they use advanced monitors) to display 3 different states when the elevator is moving, on the current floor or on a different floor and ready to be called.

I got it to work for one button, but I need the elevator to send its message to all of the call buttons. Then I read about this channel feature and it's absolutely perfect for that.

#46 Abdiel

  • Members
  • 16 posts

Posted 23 February 2013 - 04:16 AM

If you're specifically watching for modem messages, and not any other events, you don't need to wrap the event in a table.

local side, messageChannel, replyChannel, message, distance = os.pullEvent("modem_message")


#47 MudkipTheEpic

  • Members
  • 639 posts
  • LocationWhere you'd least expect it.

Posted 23 February 2013 - 08:17 AM

View PostAbdiel, on 23 February 2013 - 04:16 AM, said:

If you're specifically watching for modem messages, and not any other events, you don't need to wrap the event in a table.

local side, messageChannel, replyChannel, message, distance = os.pullEvent("modem_message")

No, you forgot the event. It's:
local event, side, messageChannel, replyChannel, message, distance = os.pullEvent("modem_message")


#48 Bubba

    Use Code Tags!

  • Moderators
  • 1,142 posts
  • LocationRHIT

Posted 23 February 2013 - 11:10 AM

View PostAbdiel, on 23 February 2013 - 04:16 AM, said:

If you're specifically watching for modem messages, and not any other events, you don't need to wrap the event in a table.

local side, messageChannel, replyChannel, message, distance = os.pullEvent("modem_message")

Like Mudkip said, using os.pullEvent(param) will still return the event so you need to capture that as well. But the reason that I use the table is for convenience, not because it is required. Writing args = {os.pullEvent()} is much neater and simpler than having 5 different variables as long as you can remember what each specific event returns.

#49 TwelveEight

  • Members
  • 16 posts
  • LocationIn the TARDIS, somewhere in time and space

Posted 25 February 2013 - 09:47 AM

Hm... would it not be possible to set the integer channel to be a variable, then have a loop scan open channels or something?

^Not a detailed question, but just a thought.

#50 Bubba

    Use Code Tags!

  • Moderators
  • 1,142 posts
  • LocationRHIT

Posted 25 February 2013 - 02:32 PM

View PostTwelveEight, on 25 February 2013 - 09:47 AM, said:

Hm... would it not be possible to set the integer channel to be a variable, then have a loop scan open channels or something?

^Not a detailed question, but just a thought.

Yup. Easily possible.

local function listen()
  while true do
	local evts = {os.pullEvent()}
	if evts[1] == "timer" then
	   return
	elseif evts[1] == "modem_message" then
	   print("Message: "..evts[4])
	end
  end
end

local max = 65535
local large = 128
while true do
for i=1, max, large do
  for x=i, i+large do
	modem.open(x)
  end
	os.startTimer(2) --Listen for two seconds and then move on to the next range
	listen()
  for x=1, i+large do
	modem.close(x)
  end
end
end

Of course, the above sample is ridiculously simple and if I were to do this in game I would probably add a table of channels that should always be listened to as soon as one message was received on the channel.

#51 WAKU

  • Members
  • 3 posts

Posted 12 March 2013 - 04:25 AM

thank u for sharing. That's useful.

#52 Abdiel

  • Members
  • 16 posts

Posted 12 March 2013 - 10:02 PM

View PostBubba, on 23 February 2013 - 11:10 AM, said:

View PostAbdiel, on 23 February 2013 - 04:16 AM, said:

If you're specifically watching for modem messages, and not any other events, you don't need to wrap the event in a table.

local side, messageChannel, replyChannel, message, distance = os.pullEvent("modem_message")

Like Mudkip said, using os.pullEvent(param) will still return the event so you need to capture that as well. But the reason that I use the table is for convenience, not because it is required. Writing args = {os.pullEvent()} is much neater and simpler than having 5 different variables as long as you can remember what each specific event returns.

Apologies for the mistake, you are indeed correct.

Perhaps a cleaner way to do it would be through symbolic constants:

local EVENT = 1
local MODEM_SIDE = 2
local MODEM_MESSAGE_CHANNEL = 3
local MODEM_REPLY_CHANNEL = 4
local MODEM_MESSAGE = 5
local MODEM_DISTANCE = 6
local TIMER_ID = 2

[...]

local timer = os.startTimer(10)
local e = {os.pullEvent()}
if e[EVENT] == "modem_message" then
  msg = e[MODEM_MESSAGE]
  replyChannel = e[MODEM_REPLY_CHANNEL]
  -- process the message

elseif e[EVENT] == "timer" and e[TIMER_ID] == timer then
  print("Timeout")
end


#53 no9name909

  • Members
  • 5 posts

Posted 13 March 2013 - 07:09 AM

Thanks for the tutorial but I don't really understand what the reply channel is for with sending a message.
Does it make any difference when I change it to an other number?

#54 Bubba

    Use Code Tags!

  • Moderators
  • 1,142 posts
  • LocationRHIT

Posted 13 March 2013 - 07:30 AM

View Postno9name909, on 13 March 2013 - 07:09 AM, said:

Thanks for the tutorial but I don't really understand what the reply channel is for with sending a message.
Does it make any difference when I change it to an other number?

Nope. It's really only there to be useful. I could change it to any number and still be able to send back on the channel of my choice.

#55 Abdiel

  • Members
  • 16 posts

Posted 13 March 2013 - 02:29 PM

The old rednet API used to be able to give you the ID of the computer which sent you a message. The modem API doesn't give you this by itself. If this is important for you, you can use the reply channel to transmit that. Otherwise, feel free to use it as an additional int value you can transmit for free.

#56 Xenres

  • Members
  • 5 posts

Posted 15 May 2013 - 12:04 AM

My question is, how many messages can traverse a single channel at the same time? I can imagine something like TCP/IP being implemented, wrapped like so -- (packet[start_identifier][target_id][source_id][message_block][end_identifier]) The message block could be encoded for security, so that messages can only be read by target machine, or any machine where the hacker has figured out how to decrypt the packets he's intercepted. If only one message can go over the channel at a time, which does make sense, I'd imagine some sort of token ring structure, where every computer has to wait its turn to transmit on that channel. By having 128 channels available, you could use multiple channels, and just send on whichever channel you have an open send ability. I don't want to go into the logistics of it, but I'll be doing some sort of experiment in single player mode. I really think we need some sort of networking stack to take advantage of this, and then you could build services that utilize it. I'm going to try and come up with some proof of concept code, as I don't think I'm explaining myself very well.

#57 Geforce Fan

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

Posted 17 May 2013 - 06:24 PM

Can you PM people within channels?
Also, I'm trying to sniff on channel 0, which is the channel for private rednet messages right?
I can't seem to see it. (No, I'm not sniffing other people's messages, just testing the security of my own)

#58 Bubba

    Use Code Tags!

  • Moderators
  • 1,142 posts
  • LocationRHIT

Posted 17 May 2013 - 08:27 PM

View PostIcanbreathecode, on 17 May 2013 - 06:24 PM, said:

Can you PM people within channels?
Also, I'm trying to sniff on channel 0, which is the channel for private rednet messages right?
I can't seem to see it. (No, I'm not sniffing other people's messages, just testing the security of my own)

You could write a program that simulates a PM using encryption, but it won't actually be private due to the fact that there is no such thing as private messages anymore. The rednet api will use the ID of the computer that sends the message as the second argument of transmit, but it sends messages on the channel that you specify with rednet.send([channel], message).

Now broadcast messages use channel 65535, if that is what you are referring to.

#59 BigSHinyToys

  • Members
  • 1,001 posts

Posted 17 May 2013 - 09:23 PM

View PostIcanbreathecode, on 17 May 2013 - 06:24 PM, said:

Can you PM people within channels?
Also, I'm trying to sniff on channel 0, which is the channel for private rednet messages right?
I can't seem to see it. (No, I'm not sniffing other people's messages, just testing the security of my own)

The Old rednet was a java level system that was secure. The new rednet (api) is a protocol built on peripheral calls to modem peripherals and is not secure. This is basically how it all works now.

Broadcast messages are all on CH: 65535

First rednet Opens out receive channel witch is out ID example our computer is 5
local modem = peripheral.wrap("left")
modem.open(os.getComputerID()) -- this will get Out ID

when I rednet.send(7,"hello world!") the api dose this modem.transmit(7,5,"Hello world!")
remembering modem.transmit(<CH>,<CH to reply on>,<payload / message>)

The receiving computer is 7 and has opened its ID as well. That means it will now get that message on channel 7 this computer will output the event "rednet_message",5,"hello world!",8 <8 is the distance in meters> that is how we know what computer sent to us . Now this is where it gets interesting. We can directly control the modem and spoof fake ID's or use one channel for sending and receiving.

broadcasts are always on CH: 65535 so the api also opens this channel for receiving. When we do rednet.broadcast("Hello World") the api dose modem.transmit(65535,5,"Hello world!") so we still see a sender ID.

If people are using the old rednet protocols to listen in all you need to do it open the channel that is there ID and you can monitor all traffic. you will have to peripheral.wrap() it your self and open the channels manually also you will be looking at "modem_message" not "rednet_messages" they are slightly different in that they tell is the channel that was sen on as well as the channel the sender wants us to reply to
<"modem_message">, <side message received on eg "back">, <CH send on eg: 7>,
<CH preferred reply channel eg:5>, <payload/message eg: "hello world!">, <distance in meaters eg:8>

#60 makerimages

  • Members
  • 236 posts

Posted 30 July 2013 - 03:47 AM

View PostBubba, on 09 February 2013 - 05:18 PM, said:


Opening channels:
Opening channels is simple. All you have to do is...
local desiredChannel = 1
modem.open(desiredChannel)
But what does opening a channel mean exactly? Well, until you've opened a channel you cannot receive any messages on that channel. You can send messages though, so if all you need to do is send a bunch of messages then there is no need to open a channel.
Note: You can open 128 channels at any given time and receive messages on them.
Note 2: The largest channel you can open is 65535


Does the 128 channel limitation apply for a specific modem, a specific computer or the entire world?





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users