Communicate between two Yun without knowing the IP

Hi,

I have two Yuns that need to communicate via wifi, but they won’t always have the same IP-address.

What is the easiest way to accomplish this? I am thinking about having them write to a database and periodically check if the other one has written anything. They just need to send a single integer to the other when a sensor is activated.

Thanks!

Change wifi dhcp client get ip from router ip pool to static ip:

Only change ethernet dhcp client get ip from router ip pool to static ip.

uci set network.wan.proto=static
uci set network.wan.ipaddr=192.168.241.1
uci set network.wan.netmask=255.255.255.0
uci commit network
/etc/init.d/network restart

Plan B:

If your router supports DHCP reservation setting. This could also be called "DHCP Static Lease" or something similar.

http://www.ubeeinteractive.com/support/consumers/faq/how-do-i-configure-dhcp-static-lease

Thanks! But I think I didn't explain it enough. The Yuns will be moved around and be connected to different networks by people who don't know how to reprogram them. So the problem is not that the IP is not static, it is that the Yuns will never know the other ones IP.

Maybe I could upload the IP once the Yun is connected and let the other one read it?

It is ideal application for Bonjour service. However Yun supports Bonjour service only, no Bonjour client support at Yun.

Set private ip address registration server which has public ip address. The registration server supoort 2 methed:

  • Insert machine name with Yun mac address, private ip address.
  • Query machine name with Yun mac address, get private ip address.

It might be reinvent wheel

sonnyyu: It is ideal application for Bonjour service. However Yun supports Bonjour service only, no Bonjour client support at Yun.

@SomethingClever, to be clear on what SonnyYu is saying. Bonjour service is on the default Yun - the factory setting. So you can setup one of the Yun with a unique name. However, the other Yun does not have the software to be a client to the Bonjour service.

However, if both Yuns can access the Internet, you could setup a registry to hold the IP of each and perhaps connect that way. Is that what you were thinking?

Jesse

Thank you both! I will read into it.

@jessemonroy650

Yes, I was thinking something like that. Either that or just make them read the integer from the database. The last solution is probably the easiest with my limited coding experience :)

It’s surprising to me that you can’t just use the “arduino.local” style name to access one Yun from another Yun.

I set up statistics monitoring according to THIS THREAD including setting up a network plugins to collect data on one Yun and send to another. On the one Yun, I set up a server interface to send data to Yun2.local, and on the other I set up a listener interface to receive data from Yun1.local. I did not enter IP addresses, and yet the data was properly sent from one to the other. (See attached image.)

Yet, if I SSH into one of them, and try to ping the other, it says it’s a bad address.

Why would collectd be able to resolve the address, yet ping can’t?

ShapeShifter: It's surprising to me that you can't just use the "arduino.local" style name to access one Yun from another Yun.

::::SNIP::::

Why would collectd be able to resolve the address, yet ping can't?

@ShapeShifter, Apparently, I'm missing something. I'll look into this.

http://wiki.openwrt.org/doc/howto/statistic.collectd

Okay, after the third link, this was clear.

Google: openwrt collectd

https://collectd.org/features.shtml

[b]Sophisticated network code[/b]

collectd utilizes a data push model, i.e. the data is collected and sent (pushed) to a multicast group or server. Thus there is no central instance which queries any values.

Multicast is the key. To be clear on this, Multicast does NOT resolve any addresses. Multicast puts out a packet on special IP address and other computers are supposed to listen.

If you look at the dump from ifconfig, it looks like the section below. In the middle of that you'll see MULTICAST. It's enabled and compiled into the kernel. You can catch the packets with any program, if you know the IP. The wikipedia article should have the address.

wlan0     Link encap:Ethernet  HWaddr 00:19:d2:9f:12:a7  
          inet addr:192.168.1.180  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2602:306:344e:9880::47/128 Scope:Global
          inet6 addr: 2602:306:344e:9880:b994:bed0:925a:214e/64 Scope:Global
          inet6 addr: 2602:306:344e:9880:219:d2ff:fe9f:12a7/64 Scope:Global
          inet6 addr: fe80::219:d2ff:fe9f:12a7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST MTU:1500  Metric:1
          RX packets:324775 errors:0 dropped:0 overruns:0 frame:0
          TX packets:247134 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:289216924 (289.2 MB)  TX bytes:43697046 (43.6 MB)

Somebody went to alot of work to make this work. It is very cool!!! Looks like Sonny and I missed this. Yes. VEry cool!! Nice work ShapeShifter.

Jesse

jessemonroy650: To be clear on this, Multicast does NOT resolve any addresses. Multicast puts out a packet on special IP address and other computers are supposed to listen.

I guess that makes sense on the surface. I will have to think about it, because I'm not sure why the sender and the receiver would need to know each other's name or address. If in were designing something like that, I would add a "connection ID" value that is passed in the packets, and which is set to the same value on the sender and receiver sides. If it doesn't resolve to an address, then why would the sender need to know the receiver's name/address, and why would the receiver need to know the sender's name address? I'll have to think this through (although it's not a high priority for me now.)

Still, this might be an idea for the OP: set up a multicast group, have each Yun join it, and talk to each other that way. The multicasts could be used for the actual communications, or just used as a setup phase to exchange their actual addresses, allowing direct communications after that. (Hmmm... maybe that's what collectd does and why it needs those names?)

Fantastic idea!

ShapeShifter:
I guess that makes sense on the surface. I will have to think about it, because I’m not sure why the sender and the receiver would need to know each other’s name or address. If in were designing something like that, I would add a “connection ID” value that is passed in the packets, and which is set to the same value on the sender and receiver sides. If it doesn’t resolve to an address, then why would the sender need to know the receiver’s name/address, and why would the receiver need to know the sender’s name address? I’ll have to think this through (although it’s not a high priority for me now.)

::::SNIP::::

@All,
Last night after I went to bed I recalled that I implemented this over a year ago for a hackathon. My boilerplater code is available on github. It is written in Python. Notes are included in the repo.

Jesse

Plan B:

Get server’s ip address at client by server’s mac address:

opkg update
opkg install fping
opkg install net-tools-arp
nano /root/getip.sh
#!/bin/ash
SERVERMACADDRESS="00:19:b9:22:ae:4a"
IP=`ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`
NETMASK=`ifconfig eth1 | grep 'inet addr:'  | cut -d: -f4`
PREFIX=`/bin/ipcalc.sh $IP $NETMASK |grep 'PREFIX=' |sed  's/\(.\{7\}\)//'`
NETWORK=`/bin/ipcalc.sh $IP $NETMASK |grep 'NETWORK=' |sed  's/\(.\{8\}\)//'`
fping -c 1 -g $NETWORK/$PREFIX > /dev/null 2>&1
SERVERIP=`/usr/bin/arp -n | grep -i $SERVERMACADDRESS | awk '{print $1}'`
echo $SERVERIP | tee /root/serverip.txt
chmod 755  /root/getip.sh
/root/getip.sh

SERVERMACADDRESS=“00:19:b9:22:ae:4a” is Yun’s server
/root/serverip.txt hold server ip address at Yun’s client

eth1: ethernet
wlan0: wifi

Plan A (Multicast way):

Send IP at server:

#!/usr/bin/python
import socket, struct, fcntl
def get_ip(iface):
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     sockfd = sock.fileno()
     SIOCGIFADDR = 0x8915
     ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
     try:
         res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
     except:
         return None
     ip = struct.unpack('16sH2x4s8x', res)[2]
     return socket.inet_ntoa(ip)
serverip=get_ip('eth1')
#print serverip
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto(serverip, (MCAST_GRP, MCAST_PORT))

Receive IP at client:

#!/usr/bin/python
import socket, struct
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))  # use MCAST_GRP instead of '' to listen only
                             # to MCAST_GRP, not all groups on MCAST_PORT
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
  print sock.recv(1024)

eth1: ethernet wlan0: wifi

Thank you very much! It looks complicated, but I will look into it :)

Sorry for the late reply - had some exams to deal with.