Things used in this project

Hardware components:
Pi 3 02
Raspberry Pi 3 Model B
×1
DC motor (generic)
×1
ULN2003
or any transistors
×1
Software apps and online services:
10
Microsoft Windows 10 IoT Core

Code

AppService codeC#
public sealed class WebServerBGTask : IBackgroundTask
{
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        // Associate a cancellation handler with the background task. 
        taskInstance.Canceled += OnCanceled;

        // Get the deferral object from the task instance
        serviceDeferral = taskInstance.GetDeferral();

        var appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
        if (appService != null &&
            appService.Name == "AppComService")
        {
            appServiceConnection = appService.AppServiceConnection;
            appServiceConnection.RequestReceived += OnRequestReceived;
        }
    }

    private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var message = args.Request.Message;
        string command = message["Command"] as string;

        switch (command)
        {
            case "Initialize":
                {
                    var messageDeferral = args.GetDeferral();
                    //Set a result to return to the caller
                    var returnMessage = new ValueSet();
                    HttpServer server = new HttpServer(8003, appServiceConnection);
                    IAsyncAction asyncAction = Windows.System.Threading.ThreadPool.RunAsync(
                        (workItem) =>
                        {
                            server.StartServer();
                        });
                    returnMessage.Add("Status", "Success");
                    var responseStatus = await args.Request.SendResponseAsync(returnMessage);
                    messageDeferral.Complete();
                    break;
                }

            case "Quit":
                {
                    //Service was asked to quit. Give us service deferral
                    //so platform can terminate the background task
                    serviceDeferral.Complete();
                    break;
                }
        }
    }
    private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    {
        //Clean up and get ready to exit
    }

    BackgroundTaskDeferral serviceDeferral;
    AppServiceConnection appServiceConnection;
}

public sealed class HttpServer : IDisposable
{
    string offHtmlString = "<html><head><title>DC Motor Demo</title></head><body><form action=\"dcmotor.html\" method=\"GET\"><h1>DC Motor Demo</h1><p>Active DC Motor</p><input type=\"radio\" name=\"state\" value=\"on\" onclick=\"this.form.submit()\"> On<br><input type=\"radio\" name=\"state\" value=\"off\" checked onclick=\"this.form.submit()\"> Off</form></body></html>";
    string onHtmlString = "<html><head><title>DC Motor Demo</title></head><body><form action=\"dcmotor.html\" method=\"GET\"><h1>DC Motor Demo</h1><p>Active DC Motor</p><input type=\"radio\" name=\"state\" value=\"on\" checked onclick=\"this.form.submit()\"> On<br><input type=\"radio\" name=\"state\" value=\"off\" onclick=\"this.form.submit()\"> Off</form></body></html>";
    private const uint BufferSize = 8192;
    private int port = 8003;
    private readonly StreamSocketListener listener;
    private AppServiceConnection appServiceConnection;

    public HttpServer(int serverPort, AppServiceConnection connection)
    {
        listener = new StreamSocketListener();
        port = serverPort;
        appServiceConnection = connection;
        listener.ConnectionReceived += (s, e) => ProcessRequestAsync(e.Socket);
    }

    public void StartServer()
    {
#pragma warning disable CS4014
        listener.BindServiceNameAsync(port.ToString());
#pragma warning restore CS4014
    }

    public void Dispose()
    {
        listener.Dispose();
    }

    private async void ProcessRequestAsync(StreamSocket socket)
    {
        // this works for text only
        StringBuilder request = new StringBuilder();
        using (IInputStream input = socket.InputStream)
        {
            byte[] data = new byte[BufferSize];
            IBuffer buffer = data.AsBuffer();
            uint dataRead = BufferSize;
            while (dataRead == BufferSize)
            {
                await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
                request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
                dataRead = buffer.Length;
            }
        }

        using (IOutputStream output = socket.OutputStream)
        {
            string requestMethod = request.ToString().Split('\n')[0];
            string[] requestParts = requestMethod.Split(' ');

            if (requestParts[0] == "GET")
                await WriteResponseAsync(requestParts[1], output);
            else
                throw new InvalidDataException("HTTP method not supported: "
                                               + requestParts[0]);
        }
    }

    private async Task WriteResponseAsync(string request, IOutputStream os)
    {
        // See if the request is for blinky.html, if yes get the new state
        string state = "Unspecified";
        bool stateChanged = false;
        if (request.Contains("dcmotor.html?state=on"))
        {
            state = "On";
            stateChanged = true;
        }
        else if (request.Contains("dcmotor.html?state=off"))
        {
            state = "Off";
            stateChanged = true;
        }

        if (stateChanged)
        {
            var updateMessage = new ValueSet();
            updateMessage.Add("State", state);
            var responseStatus = await appServiceConnection.SendMessageAsync(updateMessage);
        }

        string html = state == "On" ? onHtmlString : offHtmlString;
        // Show the html 
        using (Stream resp = os.AsStreamForWrite())
        {
            // Look in the Data subdirectory of the app package
            byte[] bodyArray = Encoding.UTF8.GetBytes(html);
            MemoryStream stream = new MemoryStream(bodyArray);
            string header = String.Format("HTTP/1.1 200 OK\r\n" +
                              "Content-Length: {0}\r\n" +
                              "Connection: close\r\n\r\n",
                              stream.Length);
            byte[] headerArray = Encoding.UTF8.GetBytes(header);
            await resp.WriteAsync(headerArray, 0, headerArray.Length);
            await stream.CopyToAsync(resp);
            await resp.FlushAsync();
        }

    }
}
Main UI app codeC#
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        InitGPIO();
        InitAppSvc();
    }
    AppServiceConnection appServiceConnection;
    private int LEDStatus = 0;
    private const int LED_PIN = 8;
    private GpioPin pin;
    private SolidColorBrush redBrush = new SolidColorBrush(Windows.UI.Colors.Red);
    private SolidColorBrush grayBrush = new SolidColorBrush(Windows.UI.Colors.LightGray);
    private void InitGPIO()
    {
        var gpio = GpioController.GetDefault();

        // Show an error if there is no GPIO controller
        if (gpio == null)
        {
            pin = null;
            return;
        }

        pin = gpio.OpenPin(LED_PIN);
        pin.Write(GpioPinValue.Low);
        pin.SetDriveMode(GpioPinDriveMode.Output);
    }

    private async void InitAppSvc()
    {
        var listing = await AppServiceCatalog.FindAppServiceProvidersAsync("AppComService");

        var packageName = "";
        // there may be cases where other applications could expose the same App Service Name, in our case
        // we only have the one
        if (listing.Count == 1)
        {
            packageName = listing[0].PackageFamilyName;
        }
        // Initialize the AppServiceConnection
        appServiceConnection = new AppServiceConnection();
        appServiceConnection.PackageFamilyName = packageName;
        appServiceConnection.AppServiceName = "AppComService";

        // Send a initialize request 
        var res = await appServiceConnection.OpenAsync();
        if (res == AppServiceConnectionStatus.Success)
        {
            var message = new ValueSet();
            message.Add("Command", "Initialize");
            var response = await appServiceConnection.SendMessageAsync(message);
            if (response.Status != AppServiceResponseStatus.Success)
            {
                throw new Exception("Failed to send message");
            }
            appServiceConnection.RequestReceived += OnMessageReceived;
        }
    }
    private async void OnMessageReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var message = args.Request.Message;
        string newState = message["State"] as string;
        switch (newState)
        {
            case "On":
                {
                    await Dispatcher.RunAsync(
                          CoreDispatcherPriority.High,
                         () =>
                         {
                             TurnOnDcMotor();
                         });
                    break;
                }
            case "Off":
                {
                    await Dispatcher.RunAsync(
                    CoreDispatcherPriority.High,
                    () =>
                    {
                        TurnOffDcMotor();
                    });
                    break;
                }
            case "Unspecified":
            default:
                {
                    // Do nothing 
                    break;
                }
        }
    }

    private void TurnOffDcMotor()
    {
        if (LEDStatus == 1)
        {
            FlipGpio();
        }
    }

    private void TurnOnDcMotor()
    {
        if (LEDStatus == 0)
        {
            FlipGpio();
        }
    }

    private void FlipGpio()
    {
        if (LEDStatus == 0)
        {
            LEDStatus = 1;
            if (pin != null)
            {
                // to turn on the LED, we need to push the pin 'low'
                pin.Write(GpioPinValue.High);
            }
        }
        else
        {
            LEDStatus = 0;
            if (pin != null)
            {
                pin.Write(GpioPinValue.Low);
            }
        }
    }
}

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Get Nostalgic and Use Nokia 84x48 LCD with Arduino
Advanced
  • 3,086
  • 14

Protip

These 84 by 48 pixel LCDs are what you might have found in Nokia 3310. And what about using them in the Arduino projects?

Let it Snow - IoT Snow Globe with Virtual Reality Web - V2
Advanced
  • 152
  • 0

Tip the snow globe over to make it snow in VR or press the temperature sensor to raise the temp and experience smog/haze in VR.

TCP/IP Multisensor
Advanced
  • 318
  • 1

Work in progress

Arduino based sensor that communicates over TCP/IP. Can be used stand-alone or part of a Raspberry based data logger with a web UI.

TCP/IP Multisensor

Team Kallio Designs

Thermopile
Advanced
  • 703
  • 1

Work in progress

Thermostat based on Raspberry Pi 3 running Android Things with touchscreen support.

Slot Car Track
Advanced
  • 546
  • 3

Slot Car Race Track! Hurry!

Home Monitoring System Based on LattePanda, ZigBee and Azure
Advanced
  • 1,754
  • 3

Full instructions

Design your home monitoring system with LattePanda (with Windows 10 Home x64 OS), CC2530 ZigBee devices, and Microsoft Azure services.

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaFree StoreBlog