1
votes

I'm using an arduino UNO and an Ethernet Shield to create a web server to response HTTP requests.

The requests are sent by ajax XMLHttpRequest.

It's working fine with static ip address. But a want the arduindo to get a DHCP ip, so I can use it in any local network (with DHCP).

I want to discover the ip of the arduino connected on the local network. So I can use it as url to send HTTP requests.

Is it possible to do that in javascript?

3
Are you trying to get the DHCP address from within the Arduino itself (web server, node.js, javascript) or from another machine (browser + js, command line, etc.)?Andrew Philips
I'm trying to get the arduino ip address from another machine, using a HTML + javascript page. From a computer or an android phone in the same local network for example.Uirado
What I want is a way to dynamically sync an HTML+js page hosted in a machine to an arduino connected in DHCP LAN.Uirado
OK, sorry, still confused about your structure. Is the "HTML+js" running in a web server or a page in a web browser? Are you trying to get a browser to find the arduino or will a web server find the arduino? Or, is your arduino the web server and you want a browser using HTML+js to find the arduino? So, 2 machines only or 3 machines total? Also, if 3 machines, does the 3rd machine have a known addr/name? Do you control the network? What I mean is, can you send broadcast/unicast messages? Does "ping 255.255.255.255" work from the cmd line? If you answer these, I have a suggestion.Andrew Philips
The "HTML+js" is a local offline page running in a web browser. The arduino is a web server. 2 machines only.Uirado

3 Answers

3
votes

OK, thanks for answering my questions above. That helped layout the network structure and the problem you're trying to solve.

Summary of the problem

Two computers: 1 web server whose address is dynamic (DHCP) and 1 web client running AJAX and HTML. How can browser find DHCP server?

Options

This is a classic problem solved many different ways throughout the history of computer networks. I've suggested some options below.

  1. Scan for the server via TCP.
  2. Scan for the server via UDP (requires special browser library).
  3. Run a DNS server.
  4. Have Arduino signal its IP.
  5. Modify your router.
  6. Don't run DHCP - use a static IP.

tl;dr - Use Option 6 if you don't control your router, Option 5 if you do.

Option: Scan for the server

I'm assuming you know your browser machine's IP address (for example, 192.168.1.17). In this case, run through all of the address from 192.168.1.0 through 192.168.1.254 (not .255 and skip you browser machine's IP) testing for a connection to port 80. This will find every web server on your subnet, so be aware you will need a way to recognize your arduino responded to the web request in case some other web server is also listening on the network. It will also take some time to set up, test and wait for timeouts on most (252) of the addresses which don't have web servers. You will eventually find it.

I'm not a fan of this one, but it gets the job done. Warning: if you don't "own" the network, someone may be angry with you for scanning their machines. A company, school or other institution may have policies about not scanning networks.

Option: UDP from the browser

This one is great, but requires a browser plug-in and some fancy coding. UDP allows one to broadcast a message to your subnet (try ping 255.255.255.255 at a command line and watch the machines echo back their IPs). If the arduino is set to listen for UDP packets on a particular port, it can echo back to the sender of the UDP packet and let that user know it's present. This is how DNS, DHCP, ping and Apple's Bonjour work. Many IP based systems advertise services by responding to UDP requests. Clients need not know the address of the servers on the subnet, they discover them through broadcast messages on well-known UDP ports.

Unfortunately, this requires a browser modification because Javascript does not support UDP for security reasons. I understand this and agree with the security restriction. However, it has cut out a really nice feature of dynamic service discovery. If you're on Apple on the browser, you might be able to find a Bonjour emulator you can run on the Arduino and it might work ("arduino.local" might attach). This might be possible with Windows service discovery, too, if you're using a Windows client for your browser. I don't know what's available in Linux for service discovery.

I don't like any of these modifications for you. Browser, Arduino (Apple, Windows or Linux), just because it adds more moving parts and you're counting on the browser to "know" how to find the service.

Option: Run a DNS server

This isn't as bad as it sounds, but I'm not sure the Arduino could handle it. Find a very small DNS server written for the Arduino and have it respond to DNS requests. On the browser, look for a well-known machine name (e.g. "my-arduino.lan"). This essentially finesses the UDP problem above by making the Arduino the UDP server (handles DNS requests) and the browser already has name resolution s/w (like every machine on the planet).

I didn't search for Arduino DNS code, it might be too large for the Arduino and writing it may be a real PITA (pain in the butt).

Option: Arduino signals IP

In this model, you can attach a LCD to the arduino and have it present its IP address on the display. Alternatively, the arduino can send a message (via TCP) to a well known server on the network (internet or otherwise) reporting its IP address there. Your browser can query that server, pick up the IP address and then contact the Arduino directly. This introduces a 3rd machine and acts like your own hacked form of DDNS (look it up, if you're not familiar with it).

Option: Modify the router

If you own the router, you can modify the router to assign a specific IP address to the Arduino, even with DHCP. This is your best bet. Here, you control the network, can allow the Arduino to come up in DHCP while still fixing its IP address. You'll have to go through your router API (web or CLI) and figure out how to do it, it's a bit hard directing you as there are thousands of types of commercial and SOHO routers.

If you don't control the router...

Option: Use Static IP

This option is really your best. Give up on DHCP and just set the static IP of the arduino. Just make sure the IP address you pick doesn't conflict with any other servers on the subnet. That shouldn't be difficult.

I hope this helps.

2
votes

The 2 best options I think:

1) When arduino starts, gets an IP address from DHCP, arduino should make a connection to a well know service provided by you. Also, each device should have an ID, defined by you during manufacturing, like mac address or part of mac address.

So, you can print on the box something like: 5c4e6f.my-well-know-host.com

Than, as I was suggesting, each time arduino starts, it tries to connect to that service passing parameters like:

POST www.my-well-know-host.com ID: 5c4e6f IP: 192.168.1.55

than, at that service, you update a DNS table to reflect this relation:

5c4e6f.my-well-know-host.com -> resolves to 192.168.1.55

obviously, from anywhere in the world the host 5c4e6f.my-well-know-host.com will resolve to 192.168.1.55, but you will only access it from you local network.

Tip: this is some kind of DDNS, but with network discovery purposes. Tip2: there is an linux dns service called MyDNS, where the hosts are simply records inside a MySQL table, easy to maintain.

2) Network discovery

I don't know if arduino is capable to do it, but, the idea is to make arduino listen on a specific UDP port, like 4444, on any address.

So, you can build a windows app, and Android APP (I already made one android discovery for another purpose, not arduino), or, the best solution that I still researching on, is to make a custom page with some javascript code, that "looks" for devices listening on that specific port.

Works like that:

  • Device gets IP from DHCP
  • device starts a thread listening for broadcast packets on port 4444
  • a discovery app listen on another port, like 4445.
  • the discovery app announces itself using a broadcast packet to 4444 port (255.255.255.255:4444)
  • each device listening, reports back with its identification and IP to app port 4445.
0
votes

This is a code to find the server ip:

<script type="text/javascript">
    var ip = "<?php echo $_SERVER['SERVER_ADDR']; ?>";
    alert(ip);
</script>  

If you are using Johnny Five framework, then you can find APIs in that framework