Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Simple Netduino Webserver


  • Please log in to reply
33 replies to this topic

#1 hari

hari

    Advanced Member

  • Members
  • PipPipPip
  • 131 posts

Posted 27 September 2010 - 07:20 AM

Well, it's not really a webserver, but it listens to webrequests and do things based on the requested urls.
Thanks to OZ for hinting Socket.Listen() in his video.

http://www.youtube.com/watch?v=RfI-yCQXT8Y

The video shows a JQueryUI page, but the actual urls that do the work are: http://x.x.x.x/led/1 and http://x.x.x.x/led/0
See Test.htm and ConsumeNetduino.htm within the attached source.

public static void Main()
{
    WebServer webServer = new WebServer();

    while (true)
    {
        int requestLength = webServer.WaitForRequest(new RequestReceivedDelegate(RequestReceived));
        if (requestLength > 0)
        {
            //-- Build response --
            responseStr = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";
            responseStr += ProcessRequest(receivedStr);
            
            // IMPORTANT: SendResponse() sends response AND closes the connection, please call only once per request.
            webServer.SendResponse(responseStr); 
            receivedStr = "";
        }
        Thread.Sleep(100);
    }
}
Full source code attached. I'm sure it can be improved. I'm just too excited not to share.

Attached Files



#2 RvBCrS

RvBCrS

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationZutphen, Netherlands

Posted 27 September 2010 - 08:06 AM

Well, it's not really a webserver, but it listens to webrequests and do things based on the requested urls.
Thanks to OZ for hinting Socket.Listen() in his video.

http://www.youtube.com/watch?v=RfI-yCQXT8Y

The video shows a JQueryUI page, but the actual urls that do the work are: http://x.x.x.x/led/1 and http://x.x.x.x/led/0
See Test.htm and ConsumeNetduino.htm within the attached source.

public static void Main()
{
    WebServer webServer = new WebServer();

    while (true)
    {
        int requestLength = webServer.WaitForRequest(new RequestReceivedDelegate(RequestReceived));
        if (requestLength > 0)
        {
            //-- Build response --
            responseStr = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";
            responseStr += ProcessRequest(receivedStr);
            
            // IMPORTANT: SendResponse() sends response AND closes the connection, please call only once per request.
            webServer.SendResponse(responseStr); 
            receivedStr = "";
        }
        Thread.Sleep(100);
    }
}
Full source code attached. I'm sure it can be improved. I'm just too excited not to share.


Very cool! I can't wait to get my hands on my Netduino Plus! I hope it arrives soon!

Do you think this is possible on the normal Netduino (with WiZNet Shield) too?

Cheers,

Ramon
Blog: Morrison Blog
Twitter: @rvbcrs

#3 MattW

MattW

    Member

  • Members
  • PipPip
  • 23 posts

Posted 27 September 2010 - 10:33 AM

Nice!!! I thinking I could use something like this communicating using SOAP for a future project.... hmmm :)

#4 hari

hari

    Advanced Member

  • Members
  • PipPipPip
  • 131 posts

Posted 27 September 2010 - 01:19 PM

Do you think this is possible on the normal Netduino (with WiZNet Shield) too?

Possible, yes. But the networking implementation for the Netduino is not (yet) as mature as the one for Netduino Plus, so you may run into roadblocks.
If you got it working, I'd be very interested. That way I can have TWO Netduinos talking to each other via Ethernet.

#5 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 27 September 2010 - 01:25 PM

Do you think this is possible on the normal Netduino (with WiZNet Shield) too?


Should be... We are working on an update to the experimental Wiznet drivers which will add listening capabilities. Should be ready sometime in October.

You won't get the increased speed that native Ethernet provides on the Netduino Plus though...

Chris

#6 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 09 October 2010 - 02:58 AM

Do you think this is possible on the normal Netduino (with WiZNet Shield) too?


Sure you could, buy why would you want to? The solution would then take twice the space, the performance would be dwarfed by the N+ and the total price would be more expensive. (SparkFun has Netduino @ $34.95 and the Ethernet Shield @ $45.95... N+ will probably be less than that when released.)

I can see the utility of utilizing parts one already has, but I would suggest the right part for the right job - A Netduino for non-ethernet projects and an Netduino Plus for Ethernet ones.

What would be really interesting would be to build an N+ into the server and command a number of Netduinos through an RS485 serial network. :) Intersil sells some really nice RS485 drivers at really reasonable prices. They'll even give you the first 5 as development samples!

#7 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 09 October 2010 - 02:59 AM

Sure you could, buy why would you want to? The solution would then take twice the space, the performance would be dwarfed by the N+ and the total price would be more expensive. (SparkFun has Netduino @ $34.95 and the Ethernet Shield @ $45.95... N+ will probably be less than that when released.)

Just FYI...Netduino Plus will retail for $59.95 USD.

Chris

#8 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 13 October 2010 - 05:40 AM

All the better!!! Hey, any chance of something like the Arduino Pro but based on the Netduino Plus design coming around?

#9 yaksplat

yaksplat

    New Member

  • Members
  • Pip
  • 5 posts

Posted 13 October 2010 - 02:42 PM

Very awesome! I just got this running on my newly arrived netduino plus. It works great, well done. I just added a few lines to get the static IP.
            NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface networkInterface in networkInterfaces) 
            {
                networkInterface.EnableStaticIP("x.x.x.x", "255.255.255.0", "x.x.x.x");
                Debug.Print("Gateway Address: " + networkInterface.GatewayAddress);
                Debug.Print("IP Address: " + networkInterface.IPAddress); 
                Debug.Print("Subnet mask " + networkInterface.SubnetMask); 
            }


#10 yaksplat

yaksplat

    New Member

  • Members
  • Pip
  • 5 posts

Posted 13 October 2010 - 04:26 PM

Sometimes this project runs fine. Then other times it dies on this line:
newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


Any thoughts?

#11 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 13 October 2010 - 04:56 PM

Sometimes this project runs fine. Then other times it dies on this line:


Do you create multiple sockets? Does it die on the first socket creation...or after creating a few? If after a few, are you disposing of the old sockets?

Chris

#12 yaksplat

yaksplat

    New Member

  • Members
  • Pip
  • 5 posts

Posted 13 October 2010 - 07:13 PM

Do you create multiple sockets? Does it die on the first socket creation...or after creating a few? If after a few, are you disposing of the old sockets?

Chris

There's just one socket in the project. I just reset my board using MFdeploy and it's still hanging on that line.

After that unsuccessful run, then i try to re-deploy and i get a "device not found or cannot be opened" error. The program randomly deploys after that.

#13 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 13 October 2010 - 07:23 PM

Does it hang on that line permanently--or does it just hang there for a few minutes and then throw an exception? It's possible that there's a glitch in the lwIP implementation which is causing this... Chris

#14 mmw

mmw

    New Member

  • Members
  • Pip
  • 5 posts

Posted 14 October 2010 - 06:36 PM

Hello!

Web server's code running on my N+ sometimes got frozen (there was no response to Web browser).
Following solution seems to be working:

client = newSocket.Accept();
Thread.Sleep(100);


#15 g.d.carter

g.d.carter

    New Member

  • Members
  • Pip
  • 6 posts
  • LocationTopeka, KS

Posted 17 October 2010 - 01:02 AM

First I do love this code, although I would like to switch it to an interrupt based web server, but I'll get to that later. For learning how to use a simple web server this was a great example. I am trying to make a change to grab or change the value of an IO port based on the 3 values. I could write this with a ton of code and many objects but I'm sure there is a better way to do this I hope someone can point out.

Here are my static ports.

        static OutputPort led13 = new OutputPort(Pins.GPIO_PIN_D13, false);
        static OutputPort led12 = new OutputPort(Pins.GPIO_PIN_D12, false);
        static InputPort in0 = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled);
        static InputPort in1 = new InputPort(Pins.GPIO_PIN_D1, false, Port.ResistorMode.Disabled);

Here is a rough copy of the ProcessRequest function that I have been working on.

        private static string ProcessRequest(string receivedStr)
        {
            //-- Parse the first line of the request: "GET /led/1 HTTP/1.1\r" --
            string firstLine = receivedStr.Substring(0, receivedStr.IndexOf('\n'));
            string sReturn = "Command executed at " + DateTime.Now.ToString();
            string[] words = firstLine.Split(' ');
            string[] parts = words[1].Split('/');
            string cmd = parts.Length > 1 ? parts[1] : "";
            string param1 = parts.Length > 2 ? parts[2] : "";
            string param2 = parts.Length > 3 ? parts[3] : "";
            object selport;

            //-- Add more commands and param handling here --
            switch (cmd)
            {
                case "led13":
                    selport = (OutputPort) led13;
                case "led12":
                    selport = (OutputPort)led12;
                case "in0":
                    selport = (InputPort) in0;
                case "in1":
                    selport = (InputPort)in1;
                default:
                    sReturn = "Unknown Command at " + DateTime.Now.ToString();
                    break;
            }
            

            if (selport != null)
            {
                switch (param1)
                {
                    case "state":
                        if (selport.Read())
                            sReturn = "Led is On at " + DateTime.Now.ToString();
                        else
                            sReturn = "Led is Off at " + DateTime.Now.ToString();
                        break;
                    case "set":
                        if (typeof(selport) == typeof(InputPort))
                        {
                            selport.Write(param2 == "1");
                        }
                        break;
                    default:
                        sReturn = "Unknown Parameter at " + DateTime.Now.ToString();
                        break;
                }

            }


            //-- Optional string to return to caller --
            return sReturn;
        }

Is there an easier way to do this with mixed Input and Output ports?

#16 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 October 2010 - 01:09 AM

Is there an easier way to do this with mixed Input and Output ports?

Hi Yacko,

Welcome to the Netduino community.

One quick thought...you could create a collection of your InputPorts/OutputPorts along with a set of string identifiers...and then evaluate your input against that collection.

Chris

#17 g.d.carter

g.d.carter

    New Member

  • Members
  • Pip
  • 6 posts
  • LocationTopeka, KS

Posted 17 October 2010 - 03:11 AM

Hi Yacko,

Welcome to the Netduino community.

One quick thought...you could create a collection of your InputPorts/OutputPorts along with a set of string identifiers...and then evaluate your input against that collection.

Chris

I had thought about that but I was having problems mixing inputport and outputport types in one collection and being able to use them in the same collection.

#18 g.d.carter

g.d.carter

    New Member

  • Members
  • Pip
  • 6 posts
  • LocationTopeka, KS

Posted 17 October 2010 - 03:57 AM

Here is the code I ended up implementing for this.

The main function that was supplied by Hari that I modified.
        private static string ProcessRequest(string receivedStr)
        {
            //-- Parse the first line of the request: "GET /led/1 HTTP/1.1\r" --
            string firstLine = receivedStr.Substring(0, receivedStr.IndexOf('\n'));
            string sReturn = "Command executed at " + DateTime.Now.ToString();
            string[] words = firstLine.Split(' ');
            string[] parts = words[1].Split('/');
            string cmd = parts.Length > 1 ? parts[1] : "";
            string param1 = parts.Length > 2 ? parts[2] : "";
            string param2 = parts.Length > 3 ? parts[3] : "";
            bool bValue;

            bValue = param2 == "1" ? true : false;

            //-- Add more commands and param handling here --
            switch (cmd)
            {
                case "led13":
                    sReturn = ProcessOutputPort(led13, param1 ,ref bValue);
                    break;
                case "led12":
                    sReturn = ProcessOutputPort(led12, param1,ref bValue);
                    break;
                case "in0":
                    sReturn = ProcessInputPort(in0, param1,ref bValue);
                    break;
                case "in1":
                    sReturn = ProcessInputPort(in1, param1,ref bValue);
                    break;
                default:
                    sReturn = "Unknown Command at " + DateTime.Now.ToString();
                    break;
            }

            //-- Optional string to return to caller --
            return sReturn;
        }


The code to process InputPorts

        private static string ProcessInputPort(InputPort inport, string sAction,ref Boolean bValue )
        {
            string sreturn;
            switch (sAction)
            {
                case "state":
                    bValue = inport.Read();
                    sreturn = "Port is " + (bValue ? "On" : "Off");
                    break;
                default:
                    sreturn = "Unknown Parameter at " + DateTime.Now.ToString();
                    break;
            }
            return sreturn;
        }

And the code for the output ports
        private static string ProcessOutputPort(OutputPort outport, string sAction,ref Boolean bValue)
        {
            string sreturn;
            switch (sAction)
            {
                case "state":
                    bValue = outport.Read();
                    sreturn = "Port is " + (bValue ? "On" : "Off");
                    break;
                case "set":
                    outport.Write(bValue);
                    sreturn = "Port set to " + (bValue ? "On" : "Off");
                    break;
                default:
                    sreturn = "Unknown Parameter at " + DateTime.Now.ToString();
                    break;
            }
            return sreturn;
        }

Now I just need to make the changes to do something instead of just write back to the browser that I determined something.

#19 hari

hari

    Advanced Member

  • Members
  • PipPipPip
  • 131 posts

Posted 17 October 2010 - 05:59 AM

Yacko,
Good job on getting that to work.
I think your code is fine, but I just want to mention that you can put as many parameters as you want by adding more paramX lines (note that write command uses three parameters ).
string cmd = parts.Length > 1 ? parts[1] : "";
string portType = parts.Length > 2 ? parts[2] : "";   		// in or out
int portIndex = int.Parse(parts.Length > 3 ? parts[3] : "0"); // 0..n
int portValue = int.Parse(parts.Length > 4 ? parts[4] : "0"); // value (only used for writes)
So, you could send urls in these formats:
read/in/portIndex
read/out/portIndex
write/out/portIndex/value

A little cleaner than hardcoding a new command for each port. But to be honest, I envision commands to be more like:
Open/GarageDoor
Close/GarageDoor
ReadTemperature/Outdoor
ReadWaterLevel/Basement

#20 Jose Torres

Jose Torres

    New Member

  • Members
  • Pip
  • 9 posts

Posted 19 October 2010 - 08:10 PM

Wow! Nice work hari. Simple yet really cool. Can't wait to see more in the future.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.