BradC
BradC

Reputation: 13

How can I have an Arduino web server tell a browser client to re-load a local URL?

I need to remotely control a solenoid with an Arduino, from about 2000 feet away. So far, it works: I designed a control circuit that fires based upon a logic-level signal from pin 9.

My problem: the initial Arduino code sent up a web page over ethernet each time the form was submitted, but if the user tried to toggle the state too quickly, the transmission was interrupted and the whole system puked. It was also slow to load.

My attempted solution: I created an HTML document on a local page to do what I need done, and indeed it does: I can control the Solenoid. However once the links which control the commands are submitted, there's no redirect back to the local control page, and after much Google-fu I can't seem to implement it in this way. Is this possible? Is this a good approach?

<HTML>
    <HEAD>
        <TITLE>Sensor-Cleaning Control</TITLE>
    </HEAD>
    <BODY>
        <H1>Solenoid Remote Actuation</H1>
        <hr />
        <br />
        <a href="http://192.168.0.88/?sol_on">Turn On Solenoid</a>
        <a href="http://192.168.0.88/?sol_off">Turn Off Solenoid</a><br /> 
        <button type="button" onclick="location.href='http://192.168.0.88/?sol_on'">On</button>
        <button type="button" onclick="location.href='http://192.168.0.88/?sol_off'">Off</button>
        <button type="button" onclick="location.href='http://192.168.0.88/?toggle'">Toggle</button>
        <br />
        <p>(Check pin 9 LED ''L9'' to make sure this code is working)</p>
    </BODY>
</HTML>

So if the Arduino sees "sol_on" it turns the solenoid on; "sol_off" off, and you can guess what "toggle" does. I'm pretty comfortable coding, but I know nothing of javascript, CSS, or PHP. I'm not afraid of implementing those, it just needs to be clear for me to do so. Note that there's some redundancy in the code above, I left it so that I could test multiple approaches to the UI.

Upvotes: 1

Views: 8527

Answers (3)

vcc2gnd
vcc2gnd

Reputation: 137

No need to add any library / framework to accomplish what you need. Even you can achieve it without javascript at all. Simply add an invisible IFRAME in your HTML file with name attribute set. In following example we'll use "Arduino" as the IFRAME's name, but you can use any valid element name you'd like.

<IFRAME name="Arduino" style="display:none"></IFRAME>

Next, add target attribute on your link element (the 'A' tags) with value specified as the IFRAME's name, i.e.:

<A href="http://192.168.0.88/?sol_on" target="Arduino">Turn On Solenoid</A>

When you click on the link, request sent to your Arduino and resulting response will be directed to the the invisible IFRAME without navigating away from currently viewed page.

For the button element, prefix location.href in onclick handler with the IFRAME's name:

<BUTTON onclick="Arduino.location.href='//192.168.0.88?sol_on';">On</BUTTON>

Upvotes: 0

Matt Gibson
Matt Gibson

Reputation: 38238

If I'm understanding you correctly, your best approach would probably be to use Ajax, where your web page uses an asynchronous Javascript call to do the toggling/on/off.

Effectively, you have the web page as shown, but instead of links to the Arduino "pages", clicking each link fires off an asynchronous request to the Arudino page, leaving your current page in the browser while still prodding the URL on the Arduino web server.

If you're not that familiar with Javascript, possibly a sensible approach would be to use jQuery, a Javascript library which insulates you somewhat from differences between browsers, and encapsulates things like Ajax requests quite nicely.

Here are some simple steps:

1) Download the latest production jQuery. I'm using 2.0.3 from here for this example.

2) Put it in the same directory as your web page, so we can include it easily.

3) Convert your web page to use Ajax with jQuery. (I've also converted it to something a little closer to the current web standard, HTML5):

<!DOCTYPE html>
<html>
    <head>
        <title>Sensor-Cleaning Control</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <!-- Include jQuery so we can use its simple goodness -->
        <script src="jquery-2.0.3.min.js"></script>
        <script>
          /* This function will be called by the onclick handlers of the buttons */
          function solenoid(url) {
            // Use jQuery's Ajax functionality to prod the given URL without
            // reloading this page or visiting another one:
            $.ajax(url);
          }
        </script>
    </head>
    <body>
        <h1>Solenoid Remote Actuation</h1>
        <button type="button" onclick="solenoid('http://192.168.0.88/?sol_on');">On</button>
        <button type="button" onclick="solenoid('http://192.168.0.88/?sol_off');">Off</button>
        <button type="button" onclick="solenoid('http://192.168.0.88/?toggle');">Toggle</button>
        <p>(Check pin 9 LED ''L9'' to make sure this code is working)</p>
    </body>
</html>

The main things to note are:

1) The inclusion of the jQuery library, so we can use its ajax() call and fire off http requests in the background with ease no matter which browser we're on.

2) I've replaced your existing onclick events with a call to a new function called solenoid, that takes a URL as a parameter.

3) The solenoid function, defined in the <script> at the top, takes the URL that was passed in and uses jQuery's ajax() call to poke the given URL. This happens in the "background", i.e. without any page (re)load.

From here, you could expand this in all sorts of ways. This code could, for example, read a short response from the Arduino and handle it in the background, too, perhaps indicating the current state of the solenoid.

(Given the simplicity of what I'm doing here, I'm sure this could be done in a more "lightweight" way in pure Javascript without jQuery, but that would have involved a chunk more slightly scary code in this example to ensure the Ajax stuff worked in many different browsers -- there's some browser inconsistency in how the underlying object (an XMLHttpRequest) used by Ajax is created. I figured for a Javascript beginner, simpler was probably better...)

Upvotes: 2

jollyroger
jollyroger

Reputation: 74

Well, i don't know your Arduino's based http server, but it certainly shall reply all requests, either with an 200 http status, that means "OK" or with any other error message like 400, that means "Bad Request". While your web application is waiting for a response, you can block (or hide) the page (or some elements) so the user will be unable to start a click-frenzy and mess up everything while he should be waiting the server's (Arduino) response.

You can use an ajax call using JQuery, so you will be able to "do something" after calling the url with your "Arduino code", either in case of success or fail.

Please see the example below:

<html>
<head>
    <script src="../scripts/jquery-2.0.3.min.js"></script>  
    <script>
        function callArduinoCode(var code) {
            jQuery.ajax({
                type: "GET",
                url: "http://192.168.0.88/?" + code,
                data: dados,
                beforeSend: function() {
                    // Hide links, show loading message...
                    $("#controls").css("display","none");
                    $("#loading").css("display","block");
                },
                success: function( data ){  
                    // Hide loading message, show links again...
                    $("#controls").css("display","block");
                    $("#loading").css("display","none");                
                },
                error: function (xhr, ajaxOptions, thrownError){
                    alert("Failed, HTTP Status was " + xhr.status);
                    // Hide loading message, show links again...
                    $("#controls").css("display","block");
                    $("#loading").css("display","none");
                }  
            });
        return false;       
        }
    </script>       
</head>
<body>
    <div id="controls">
        <!-- your links here -->
        <a onClick="callArduinoCode('sol_on'); return false;">Turn Solenoid ON</a>
        <a onClick="callArduinoCode('sol_off'); return false;">Turn Solenoid OFF</a>
    </div>
    <div id="loading" style="display:none;">
        Loading, please wait...
    </div>
</body> 
</html>

You can get JQuery at jquery.com

Good Luck!

Upvotes: 0

Related Questions