Blinky WebServer Sample

The classic LED blinking app controlled by another app's WebServer.

Blinky Webserver Sample

We’ll create a simple Blinky app controlled by another app’s WebServer and connect a LED to your MinnowBoard Max (or MBM for short).

Load the project in Visual Studio

You can find this sample in the Samples\App2App WebServer folder.

Make sure you set the ‘Remote Debugging’ setting to point to your MBM. Go back to the basic ‘Hello World’ sample if you need guidance.

Make sure you connect the LED to your MBM. Go back to the basic ‘Blinky’ sample if you need guidance.

Let’s look at the code

We are demonstrating two ideas with this sample: how to implement a WebServer and how to enable app-to-app communication. To demonstrate this, the sample contains:

WebServerApp

To create a WebServer that can communicate with our Blinky app, we need to do two things: implement an actual server and enable app-to-app communication. At the core of our server implementation is a ‘StreamSocketListener’.
Here is a simplified version of what we need to implement this:

public sealed class HttpServer : IDisposable
{
    public void StartServer(int port)
    {
        // Create and bind our StreamSocket to a port and process
        // requests as they arrive
        StreamSocketListener listener = new StreamSocketListener();
        listener.BindServiceNameAsync(port.ToString());
        listener.ConnectionReceived += (s, e) => 
            {
                // Read request from the socket
                using (IInputStream input = e.Socket.InputStream)
                {
                    . . .
                    await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
                    . . .
                }

                // Parse request and compose response
                . . .

                // Write response to the socket
                using (IOutputStream output = socket.OutputStream)
                {
                    using (Stream resp = output.AsStreamForWrite())
                    {
                        // Update the WebServer client
                        . . .
                    }
                }
            }
        }
    }
}

To be allowed to function as a server, we need to add a new capability to the Package.appxmanifest:

<Capabilities>
    <Capability Name="internetClient" />
    <Capability Name="internetClientServer" />
</Capabilities>

To be allowed to communicate with other apps, we need to add some special configuration to Package.appxmanifest. Specifically, we to add the extension: ‘windows.appService’. This extension requires two pieces of information:

  1. The extension’s EntryPoint attribute must specify the Namespace and Class of a BackgroundTask. This BackgroundTask will provide the implementation of our app-to-app communication.
  2. The AppService’s Name attribute must specify the name of our app-to-app communication service. This service name can be thought of, in conjunction with this Application’s PackageFullName, as the address of the connection which is used for all apps communicating.

These properties can be modified like this:

<Applications>
    <Application Id="App">

        . . .
        
        <Extensions>
            <uap:Extension Category="windows.appService" EntryPoint="WebServerTask.WebServerBGTask">
                <uap:AppService Name="Ap2AppComService" />
            </uap:Extension>
        </Extensions>
    </Application>
</Applications>

At this point, all of the requisite building blocks have been established. We can focus on putting them together. First, our BackgroundTask must be implemented. A BackgroundTask is a simple implementation of the IBackgroundTask interface which consists of a ‘Run’ method. The implementation of our WebServer and app-to-app communication must begin in this method.

For our WebServer, our BackgroundTask must instantiate our WebServer and implement our app-to-app communication.

BackgroundTaskDeferral _serviceDeferral;

public void Run(IBackgroundTaskInstance taskInstance)
{
    // Get the deferral object from the task instance
    _serviceDeferral = taskInstance.GetDeferral();

    var appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
    if (appService != null && appService.Name == "Ap2AppComService")
    {
        // Start our WebServer asynchronously
        HttpServer server = new HttpServer();
        IAsyncAction asyncAction = Windows.System.Threading.ThreadPool.RunAsync(
            (workItem) =>
            {
                // We can pass our AppServiceConnection instance to the WebServer to
                // allow it to participate in the app-to-app communication
                server.StartServer(appService.AppServiceConnection);
            });

        // Implement the app-to-app communication service request listener
        appService.AppServiceConnection.RequestReceived += (sender, args) => 
            {
                var message = args.Request.Message;

                // We can handle various requests from other apps here and respond using
                // 'await args.Request.SendResponseAsync'
                . . .
            };
    }
}

BlinkyApp

The client app is very similar to the Blinky sample. The major addition here is that we are allowing a WebServer to be used to configure the on/off state for our LED. To establish a connection with the WebServer app via the app-to-app mechanism, we need to create an AppServiceConnection object, configure it with information from the WebServer app, and send/receive messages.

// Initialize the AppServiceConnection
AppServiceConnection appServiceConnection = new AppServiceConnection();
// Provide the PackageFullName of the WebServerApp
appServiceConnection.PackageFamilyName = "WebServer_hz258y3tkez3a";
// Provide the AppService Name specified in WebServerApp's Package.appxmanifest
appServiceConnection.AppServiceName = "Ap2AppComService";

// Establish the app-to-app connection
var res = await appServiceConnection.OpenAsync();
if (res == AppServiceConnectionStatus.Success)
{
    appServiceConnection.RequestReceived += (sender, args) =>
        {
            // Messages received can be handled here as needed
            . . .
        };

    // We can send messages via 'appServiceConnection.SendMessageAsync'
    . . .
}

Deploy and Run Sample

To get the Blinky WebServer running, first deploy the WebServer project. This will register the app-to-app communication mechanism. Then deploy and run the Blinky project. This will start our headed Blinky app and initialize and start the app to app communication (which will also start the web server). You can then test it all with the web client as detailed in the next step.

Web Client

For our sample app, we have hosted a simple client in our WebServer. It can be accessed via the IP address and port (something like http://10.0.0.1:8000) and can be used to toggle the LED on and off

WebServer Client

Questions/Suggestions

As always, for questions and feedback, contact us.