Thursday, December 15, 2005 

Using HttpListener Asynchronously

My previous entry about creating a mini-web server application to take X10 device requests used HttpListener to wait for and respond to HTTP requests synchronously. However, as I develop a user interface for my X10Listener service, I'll need to be able to respond to those requests in the background while the user configures other areas of the service. So I've switched to an asynchronous use of HttpListener. First, in my load subroutine, I start the listener as before, but use BeginGetContext instead of GetContext.
Dim listener As New System.Net.HttpListener

listener.Prefixes.Add("http://*:33333/")

Try
    listener.Start()
Catch ex As Exception
    MsgBox(ex.Message)
    Exit Sub
End Try

listener.BeginGetContext(New System.AsyncCallback(AddressOf Me.ProcessRequest), _
listener)
Now I can go on and set up the UI and handle UI events. Note that I pass a reference to the address of another routine called ProcessRequest along with a reference to the listener object. Here is the routine to process the request, which is automatically called when an HTTP request comes in.
Private Sub ProcessRequest(ByVal result As System.IAsyncResult)

    Dim listener As Net.HttpListener
    Dim context As Net.HttpListenerContext

    listener = result.AsyncState
    context = listener.EndGetContext(result)

    ' use context.Request to explore the incoming HTTP request

    listener.BeginGetContext(New System.AsyncCallback(AddressOf _
Me.ProcessRequest), listener) End Sub
Note that I never have to instantiate a new HttpListener except during the initial load. I can pass the single listener object around via the asynchronous handler. At the end of the ProcessRequest routine, I simply set up to handle the next incoming request by calling BeginGetContext again. Next, I'll be building the UI and sending a more complex response that will include a configurable, simple HTML menu of X10 commands.

Tuesday, December 06, 2005 

Using HttpListener For X10 Web Interface

When I created my VB.NET library for the X10 CM17A, I really didn't know what I was going to use it for. It was a learning exercise. I intended my next step to be creating an ASP.NET app that I could access from the network to send X10 commands "remotely" from another machine on the wireless connection in the house. When I started that, I quickly realized that the latest version of IIS that supported the ASP.NET 2.0 applications I would be creating in VS 2005 was not available for Windows XP. Not interested in upgrading to a new operating system, I put the idea aside, noting that I could still do it some day by implementing some kind of client/server messasing protocol in a couple of separate applications.

Well today I stumbled upon the new HttpListener class while browsing through an article on streams in the latest issue of MSDN. HttpListener seemed to be just what I needed - a way to listen to and respond to HTTP requests easily. I could run a small app (kind of a mini webserver) that would listen for incoming requests on a certain port, decode the query string from the URL, and instantiate and manipulate a CM17A device via my existing module.

Keep in mind that this implementation is synchronous, but the HttpListener does allow for asynchronous operation using BeginGetContext. First, create your listener and point him at the right port.
Dim listener As New System.Net.HttpListener
listener.Prefixes.Add("http://*:33333/")
listener.Start()
Then, sit in a loop waiting for incoming requests. Once I receive a request in the proper format, I split up the string to get the house, device, and commands. Then I simply send these to the CM17A Firecracker unit using my class. Note there is not much error checking at all. I'm assuming the incoming URL has all three parameters, etc.
Do
    Dim context As Net.HttpListenerContext = listener.GetContext
    If context.Request.Url.LocalPath = "/X10" Then
        Dim paramslist As String = context.Request.Url.Query.Split("?")(1)
        Dim params() As String = paramslist.Split("&")

        Dim msg As String = DateTime.Now.ToString() & ": "
        Dim nDevice As Integer
        Dim strHouse As String = ""
        Dim strCommand As String = ""
        Dim strVal As String

        For Each stringpair As String In params
            strVal = stringpair.Split("=")(1)
            Select Case stringpair.Split("=")(0).ToUpper
                Case "DEVICE"
                    nDevice = strVal.ToUpper
                Case "HOUSE"
                    strHouse = strVal
                Case "COMMAND"
                    strCommand = strVal.ToUpper
                Case Else
            End Select
        Next

        Dim FC As New X10.CM17A(1)
        If FC.SendCommand(strHouse, nDevice, strCommand) Then
            msg += "Command sent."
        Else
            msg += "Error sending command."
        End If

        Dim b() As Byte = System.Text.Encoding.ASCII.GetBytes(msg)
        context.Response.OutputStream.Write(b, 0, b.Length)
        context.Response.Close()
   End If
Loop While True
Now, sending an OFF command to device 1 in house A is as simple as opening up a web browser and pointing it to "http://192.168.1.2:33333/X10?device=1&house=A&command=off" (or whatever IP address your listener is running on). You get back a simple success or failure message. It's amazing to use a little Windows Mobile 5.0 device to control X10 devices all over the house just by browsing an internal web "server." It would be simple to extend this idea by building a little client app that sends these HTTP requests based on button clicks.

In fact, you could just write up a little HTML page that had links to URL's that would turn your various devices on or off. This HTML could live on the listener and be returned as the response to /X10?init or something similar. There are lots of UI possibilities here.

Friday, December 02, 2005 

Might We Suggest the Enemy?

There was a deal posted over at SlickDeals.net for a collegiate hoodie + t-shirt combo for about $20, so I clicked-through to check it out. There were lots of schools available, but I found the "might we also suggest" items to be questionable. The example to the left (click for larger version) shows a suggestion of UNC slippers for someone purchasing an NC State hoodie. For those of you living outside of North Carolina that might only know about the UNC-Duke rivalry, all three of these schools hate each other. Suggesting UNC gear to a Wolfpack fan is about the most offensive suggestion you could possibly offer.

    Add to Google

    This page is powered by Blogger.



Photostream

    www.flickr.com
    justinhenry's photos More of justinhenry's photos