Run arduino code when button clicked from website hosted on Tomcat web server

I’ve got an apache tomcat web server that is hosting a website that has a button, when that button is clicked i need it to fire up some code on my arduino (i’ve got an ethernet shield and an NFC shield on it and need the code that says to ‘read tag’ to run when the button is clicked). I’ve been scowering the internet for examples and I’ve got the “Arduino Programming Getting Started with Sketches” and have read the section on ethernet but an having some trouble understanding.

I’ve taken this example to try to better my understanding:

// sketch 10-02 Internet Pins

#include <SPI.h>
#include <Ethernet.h>

// MAC address just has to be unique. This should work
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// The IP address will be dependent on your local network:
byte ip[] = { 192, 168, 1, 30 };
EthernetServer server(80);

int numPins = 5;
int pins[] = {3, 4, 5, 6, 7};
int pinState[] = {0, 0, 0, 0, 0};
char line1[100];

void setup()
{
  for (int i = 0; i < numPins; i++)
  {
     pinMode(pins[i], OUTPUT);
  }
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  EthernetClient client = server.available();
  if (client) 
  {
    while (client.connected()) 
    {
      readHeader(client);
      if (! pageNameIs("/"))
      {
        client.stop();  
        return;
      }
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();

      // send the body
      client.println("<html><body>");
      client.println("<h1>Output Pins</h1>");
      client.println("<form method='GET'>");  
      setValuesFromParams();
      setPinStates();
      for (int i = 0; i < numPins; i++)
      {
         writeHTMLforPin(client, i);
      }
      client.println("<input type='submit' value='Update'/>");
      client.println("</form>");
      client.println("</body></html>");

      client.stop();            
    }
  }
}

void writeHTMLforPin(EthernetClient client, int i)
{
  client.print("<p>Pin ");
  client.print(pins[i]);  
  client.print("<select name='");
  client.print(i);
  client.println("'>");
  client.print("<option value='0'");
  if (pinState[i] == 0)
  {
    client.print(" selected");
  }
  client.println(">Off</option>");
  client.print("<option value='1'");
  if (pinState[i] == 1)
  {
    client.print(" selected");
  }
  client.println(">On</option>");
  client.println("</select></p>");  
}

void setPinStates()
{
  for (int i = 0; i < numPins; i++)
  {
     digitalWrite(pins[i], pinState[i]);
  }
}

void setValuesFromParams()
{
  for (int i = 0; i < numPins; i++)
  {
    pinState[i] = valueOfParam(i + '0');
  }
}

void readHeader(EthernetClient client)
{
  // read first line of header
  char ch;
  int i = 0;
  while (ch != '\n')
  {
    if (client.available())
    {
      ch = client.read();
      line1[i] = ch;
      i ++;
    }
  }
  line1[i] = '\0'; 
  Serial.println(line1);
}

boolean pageNameIs(char* name)
{
   // page name starts at char pos 4
   // ends with space
   int i = 4;
   char ch = line1[i];
   while (ch != ' ' && ch != '\n' && ch != '?')
   {
     if (name[i-4] != line1[i])
     {
       return false;
     }
     i++;
     ch = line1[i];
   }
   return true;
}

int valueOfParam(char param)
{
  for (int i = 0; i < strlen(line1); i++)
  {
    if (line1[i] == param && line1[i+1] == '=')
    {
      return (line1[i+2] - '0');
    }
  }
  return 0;
}

I feel like the only difference between what is happening here and what i’m wanting is that instead of using the server on the arduino i need to use my tomcat server (i’ve got that part working, thanks to some help from forum members). The issue i’m having is understanding how things are working when the ‘update’ button is pressed. I’m used to seeing some kind of action listener or something (my programming experience is mostly Java). Thanks a lot for your help!

The full URL to the arduino will need to be put in the page not served from the arduino, somewhat like below.

<a href="http://zoomkat.no-ip.org:88/cgi-bin/echoo.bat?$00$80$F2$01$80$50">Fan</a>|

I appreciate your response, but i'm not sure how to find the URL to use as you suggested. I don't understand the example you posted unfortunetly, sorry

To connect to an arduino running behind a router, you will need to port forward on the router the incoming request to the arduino running the ethernet shield. Unless you have an assigned static ip address for your router, you will probably need to use a dynamic ip service like no-ip.com. The below shows how the links are placed in the web page. The first link would be if the page is served from the arduino, the second if the web page is inside the LAN, and the third using no-ip if accessed from the internet.

<HTML>
<HEAD>
<TITLE>Arduino GET test page</TITLE>
</HEAD>
<BODY>
<H1>Zoomkat's simple Arduino button</H1>

<a href='/?on1' target='inlineframe'>ON</a>
<a href='/?off' target='inlineframe'>OFF</a>

<a href='http://192.168.1.102:84/?on1' target='inlineframe'>ON</a>
<a href='http://192.168.1.102:84/?off' target='inlineframe'>OFF</a>

<a href='http://zoomkat.no-ip.org:84/?on1' target='inlineframe'>ON</a>
<a href='http://zoomkat.no-ip.org:84/?off' target='inlineframe'>OFF</a>

<IFRAME name=inlineframe style='display:none'>
</IFRAME>
</BODY>
</HTML>

Ok. Yeah i would likely need the no-ip.com option. But after adding that, i'm still unclear on how to implement the issue in my original post. Can you educate me on how this communication works between a web server and the arduino? Does my arduino have to have its own little server if it wants to receive a signal from a button click on a website hosted else where?

Just read a post that mentioned sending a GET/POST request using the IP of the arduino, something along these lines

xmlhttp.open("GET", "http://ipAddressOfArduino

followed by the parameters. I guess this is using AJAX? (which i've never used before). Wouls something like this be applicable to my situation?

Does my arduino have to have its own little server if it wants to receive a signal from a button click?

Yes, the arduino has to act as a server to receive request from the browser. Below is the arduino server code that has the buttons for various ways the web page is used.

//zoomkat 04-10-15
//simple button GET with iframe code
//open serial monitor to see what the arduino receives
//use the ' instead of " in html ilnes 
//address will look like http://192.168.1.102:84/ when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ethernet shield mac address
byte ip[] = { 
  192, 168, 1, 102 }; // arduino IP in lan
byte gateway[] = { 
  192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 
  255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString; 

//////////////////////

void setup(){

  pinMode(4, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("server test no-ip 04-10-15"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println("HTTP/1.1 204 Zoomkat\r\n\r\n");
          }
          else {
            client.println("HTTP/1.1 200 OK"); //send new page
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Arduino GET test page</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Zoomkat's simple Arduino button</H1>");
            client.println("Arduino served LAN: <a href='/?on1' target='inlineframe'>ON</a>"); 
            client.println("<a href='/?off' target='inlineframe'>OFF</a>

"); 

            client.println("Remote served LAN: <a href='http://192.168.1.102:84/?on1' target='inlineframe'>ON</a>"); 
            client.println("<a href='http://192.168.1.102:84/?off' target='inlineframe'>OFF</a>

"); 

            client.println("Remote served no-ip: <a href='http://zoomkat.no-ip.org:84/?on1' target='inlineframe'>ON</a>"); 
            client.println("<a href='http://zoomkat.no-ip.org:84/?off' target='inlineframe'>OFF</a>"); 

            client.println("<IFRAME name=inlineframe style='display:none'>");          
            client.println("</IFRAME>");

            client.println("</BODY>");
            client.println("</HTML>");
          }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on1") >0)//checks for on
          {
            digitalWrite(4, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(4, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";
        }
      }
    }
  }
}

Ok thank you, i'll do a bit of studying on this and get back to you, hopefully i can start to understand a bit. As for sending the request from my java web server, do i need to do something along the lines of my previous post? Send a request to the arduinos IP?

sending the request from my java web server

Basic info, web servers do not send request, they respond to request sent by web clients.

So it sounds like for what i'm wanting to do that I need a server and client on both ends? The arduino and my web page side? Because i need a little bit of back and forth. Html button click sends request to arduino, arduino runs code, sends result of that code back to the web page. Or would the final message from the arduino back to my web page (hosted in my java tomcat server) just be like a client response?

Btw, thanks so much for your responses thus far. I'm in a pretty big hurry to get this done so i'm stressing a bit

The below code shows a simple way to return data from an arduino to an iframe in a web page. Below is a page that has info on how to use more complex methods to have data put in a web page.

http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/web-server-read-switch-automatically-using-AJAX/

// zoomkat's meta refresh data frame test page 5/25/13
// use http://192.168.1.102:84 in your brouser for main page
// http://192.168.1.102:84/data static data page
// http://192.168.1.102:84/datastart meta refresh data page
// for use with W5100 based ethernet shields
// set the refresh rate to 0 for fastest update
// use STOP for single data updates

#include <SPI.h>
#include <Ethernet.h>

const int analogInPin0 = A0;
const int analogInPin1 = A1;
const int analogInPin2 = A2;
const int analogInPin3 = A3;
const int analogInPin4 = A4;
const int analogInPin5 = A5;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
unsigned long int x=0; //set refresh counter to 0
String readString; 

//////////////////////

void setup(){
  Serial.begin(9600);
    // disable SD SPI if memory card in the uSD slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.println("meta refresh data frame test 5/25/13"); // so I can keep track of what is loaded
}

void loop(){
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
         if (readString.length() < 100) {
          readString += c; 
         } 
        //check if HTTP request has ended
        if (c == '\n') {

          //check get atring received
          Serial.println(readString);

          //output HTML data header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //generate data page
          if(readString.indexOf("data") >0) {  //checks for "data" page
            x=x+1; //page upload counter
            client.print("<HTML><HEAD>");
            //meta-refresh page every 1 seconds if "datastart" page
            if(readString.indexOf("datastart") >0) client.print("<meta http-equiv='refresh' content='1'>"); 
            //meta-refresh 0 for fast data
            if(readString.indexOf("datafast") >0) client.print("<meta http-equiv='refresh' content='0'>"); 
            client.print("<title>Zoomkat's meta-refresh test</title></head><BODY>
");
            client.print("page refresh number: ");
            client.print(x); //current refresh count
            client.print("

");
            
              //output the value of each analog input pin
            client.print("analog input0 is: ");
            client.print(analogRead(analogInPin0));
            
            client.print("
analog input1 is: ");
            client.print(analogRead(analogInPin1));
                        
            client.print("
analog input2 is: ");
            client.print(analogRead(analogInPin2));
            
            client.print("
analog input3 is: ");
            client.print(analogRead(analogInPin3));
                                    
            client.print("
analog input4 is: ");
            client.print(analogRead(analogInPin4));
            
            client.print("
analog input5 is: ");
            client.print(analogRead(analogInPin5));
            client.println("
</BODY></HTML>");
           }
          //generate main page with iframe
          else
          {
            client.print("<HTML><HEAD><TITLE>Zoomkat's frame refresh test</TITLE></HEAD>");
            client.print("Zoomkat's Arduino frame meta refresh test 5/25/13");
            client.print("

Arduino analog input data frame:
");
            client.print("&nbsp;&nbsp;<a href='http://192.168.1.102:84/datastart' target='DataBox' title=''yy''>META-REFRESH</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://192.168.1.102:84/data' target='DataBox' title=''xx''>SINGLE-STOP</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://192.168.1.102:84/datafast' target='DataBox' title=''zz''>FAST-DATA</a>
");
            client.print("<iframe src='http://192.168.1.102:84/data' width='350' height='250' name='DataBox'>");
            client.print("</iframe>
</HTML>");
          }
          delay(1);
          //stopping client
          client.stop();
          //clearing string for next read
          readString="";
        }
      }
    }
  }
}

If you have a tomcat, you can run java code on it. So you can develop a servlet/jsp that use Ardulink to send a message to an Arduino board without shields!