Power Your Coffee Maker With Netduino

About the project

Control your coffee maker remotely! Create a connected coffee maker using household electricity with .NET, Netduino, and Xamarin.

Project info

Difficulty: Moderate

Platforms: MicrosoftXamarinNetduino

Estimated time: 2 hours

License: Apache License 2.0 (Apache-2.0)

Items used in this project

Hardware components

Male to Male jumper wires Male to Male jumper wires https://www.amazon.com/gp/product/B01L5UJ36U/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01L5UJ36U&linkId=deaa8d0ec43df0382cdd48475e54c39a x 1
Male to Female jumper wires Male to Female jumper wires https://www.amazon.com/gp/product/B01L5UKAPI/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01L5UKAPI&linkId=ad8190ba99e5db8df268ba63da8c48cf x 1
16-18 gauge extension cord 16-18 gauge extension cord https://www.amazon.com/gp/product/B01MTYL3HS/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01MTYL3HS&linkId=9b53c4df7aa0ec5caa4a4355a83f00f3 x 1
Keyes 2-channel relay Keyes 2-channel relay https://www.amazon.com/gp/product/B0177WOT1E/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B0177WOT1E&linkId=4663e774360250ac9b0abc3ddd15508e x 1
M3 3mm nuts M3 3mm nuts https://www.amazon.com/gp/product/B00GYS1SXU/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00GYS1SXU&linkId=c095c3d9388c6e354157d71cf45af211 x 1
12mm M3 socket screws 12mm M3 socket screws https://www.amazon.com/gp/product/B01LZPZL3W/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01LZPZL3W&linkId=c87b587ddeb943f2c9045c4670ed57c4 x 1
Half-size Breadboard Half-size Breadboard https://www.adafruit.com/product/64 x 1
Double-sided mounting tape Double-sided mounting tape https://www.amazon.com/gp/product/B00O2ZW88Q/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00O2ZW88Q&linkId=9f91228439d825d4744f59cf0ff25e3b x 1
Screw terminal blocks Screw terminal blocks https://www.amazon.com/gp/product/B00X77RIJE/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00X77RIJE&linkId=ce80d86af603f0b3256ef1a393c63b45 x 1
Coffee Maker (with on/off switch) Coffee Maker (with on/off switch) x 1
3D Printable baseboard 3D Printable baseboard You can use this 3D file, but it still needs to be printed: http://developer.wildernesslabs.co/Netduino/About/Downloads/ x 1
Heat shrink tubing Heat shrink tubing https://www.amazon.com/gp/product/B00OZSL8UE/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00OZSL8UE&linkId=e430ec351a56d28a12b8f4a49ca8055b x 1
14" female disconnects 14" female disconnects https://www.amazon.com/gp/product/B0071NC5NO/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B0071NC5NO&linkId=39d89fc78b16dcf37c7c0217bfe18c30 x 1
18 gauge (or larger) lamp cord 18 gauge (or larger) lamp cord https://www.amazon.com/gp/product/B0002YTQZO/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B0002YTQZO&linkId=2c3c9b551932dcef3b39c18dbee3b065 x 1
USB Wall Charger - 5V, 1A (Black) USB Wall Charger - 5V, 1A (Black) https://www.amazon.com/gp/product/B01M1JJ5DR/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01M1JJ5DR&linkId=d621d04bc96cf3f78063e07a69b2afbf x 1
Micro USB Cable Micro USB Cable https://www.amazon.com/gp/product/B0193ZCSDY/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B0193ZCSDY&linkId=2ec812db780f29c02e3b3677eaf19d1d x 1
Netduino3 Wifi Netduino3 Wifi https://www.amazon.com/Netduino-WLNET3W-3-Wi-Fi/dp/B01MZ127UE x 1

View all

Hand tools and fabrication machines

Solder Solder https://www.amazon.com/gp/product/B071WW6PN7/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B071WW6PN7&linkId=1b7aec97811580f4f6eae0970003ccdf x 1
Soldering iron (generic) Soldering iron (generic) https://www.amazon.com/gp/product/B00ANZRT4M/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00ANZRT4M&linkId=106cde3fdaf815ad092573544562be88 x 1
Phillips head screwdriver Phillips head screwdriver https://www.amazon.com/gp/product/B00XV9ARJG/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00XV9ARJG&linkId=05fac82ebe9ef3c6cd17945f27733f5a x 1
2.5mm hex key (for M3 socket screws) 2.5mm hex key (for M3 socket screws) https://www.amazon.com/gp/product/B000E7ZQIA/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B000E7ZQIA&linkId=dd6b1e3a48c26326ec6c25b73d7bc007 x 1
3.2mm (1/8") drill bit 3.2mm (1/8") drill bit https://www.amazon.com/gp/product/B00N3WQQSW/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00N3WQQSW&linkId=0e422721d97c44c09b2b070a84a8c569 x 1
Heat gun (or blowdryer) Heat gun (or blowdryer) https://www.amazon.com/gp/product/B00EU2T8GG/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00EU2T8GG&linkId=1c63013607d1e5557d8494df2b83e0f0 x 1
Razor blade Razor blade https://www.amazon.com/gp/product/B009OIN1CI/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B009OIN1CI&linkId=956bfa3f75961a1ab5dd8e1ec9e30604 x 1
Precision flathead screwdriver Precision flathead screwdriver https://www.amazon.com/gp/product/B01C597G9G/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01C597G9G&linkId=de67be03e27504c5ffaf279e594e8c57 x 1
Wire cutter Wire cutter https://www.amazon.com/gp/product/B00ZYQEPEC/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00ZYQEPEC&linkId=42fd53b7888cdbbf203f997d90d0c0c9 x 1
Wire stripper Wire stripper https://www.amazon.com/gp/product/B00ZYQEPEC/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=ilderneabs-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B00ZYQEPEC&linkId=42fd53b7888cdbbf203f997d90d0c0c9 x 1

View all

Story

Part 1: Connected Power

Did you know that you can power Netduino from a cheap USB charger? We were working on some Netduino-controlled appliance hacks, and I thought it would be helpful to share a quick hack to power Netduino from household electricity using a cheap USB charger that can be integrated directly into an appliance circuit.

It’s super easy, it only requires a USB charger, some appliance/lamp cord, a couple pieces of shrink wrap tubing, and 1/4″ female disconnects to make our adapter connectable to a typical household wiring circuit:

Of course, if you don’t need to tie the power into a household electrical circuit, you can just plug the adapter straight into the wall and power the Netduino from a micro USB cable.

If you’re building an appliance control circuit, however, you can use this hack to tie the Netduino power adapter directly into the circuit, so you only have one cord that needs to be plugged into the wall. For instance, we used some double sided tape to attach our USB adapter to our appliance control board, and all of our power, both for the appliance control circuit, and the Netduino is taken care of:

Step 1 - Separate and Strip the Wires

First, cut the lamp cord and then start separating it down the center with a razor blade:

Next, use your fingers to pull the cord apart, you’ll need a probably about 5cm or 2″ free:

 Once the cord is separated a bit, use a wire-stripper to pull off about a centimeter or so of the insulation:

Step 2 - Attach Female Disconnects

Once the wire is stripped, we can add the female disconnects. Slide them over the bare wire and then use a crimper to crush the disconnect attachment point onto the wire. For added protection, you can add a little solder, but it’s usually not necessary:

We’re just about ready to attach the disconnects to the adapter, but first, we need to slide some short sections of heat shrink tubing over the wire. We’ll heat this later, for now, just slide it over the end:

Step 3 - Connect to USB Charger

Once the tubing is on, attach the disconnects to the plug prongs:

They'll probably be pretty tight, so you may want to loosen them a little with a small screwdriver to fit them over:

Don't loosen them too much, they should be pretty tight on the plug prongs so they don't disconnect.

Step 4 - Heat the Heat Shrink Tubing

Now that the disconnects are on, we can finalize our work by using a heat gun (or hair dryer) to shrink the tubing and provide insulation:

That's it! Now we have a power adapter for a Netduino that we can hook directly into a household electrical circuit!

Part 2: Control

In part 1, we created a power adapter from a USB charger that can be used to power a Netduino when it isn’t plugged into the computer. In this part, we’re going to create what is, in essence, a smart power outlet; a household electrical circuit that can be turned on or off by a Netduino. In this example, we’re going to use a simple coffee pot that has an on/off switch, but any simple appliance can be controlled this way. Later on, we’ll add more complexities such as controlling this outlet via a mobile app talking to a web API on the Netduino.

WARNING:

Before going any further, it’s important to note that this project is meant to control household electricity. That’s 120V in North America, and 240V in many other places. Household electricity can kill you. It probably won’t; I’ve done enough electrical household wiring to be shocked more times than I care to admit, but in certain situations, it certainly can be deadly. When this project is assembled and plugged in, the terminal blocks and relay terminals will be live and can shock you if not handled with care. All the live conducts are protected by plastic, but if you stick metal, such as a screwdriver in them, you can get shocked. Keep this prototype away from children who might stick small fingers into the terminals or get a hold of the live wires some other way. Additionally, when not in use, it should be unplugged from the electrical outlet.

Step 1 - Print Baseboard and Clean Holes

First, we need a baseboard to put all our prototype boards on. Download and print the Appliance Control Board from our 3D print designs Github repo. If you don't have a 3D printer, you can also make one of these from a 3/16" - 1/4" thick sheet of plywood. The 3D print repo contains the original .DWG file with dimensions. AutoDesk publishes viewers to view the file to get dimensions.

3D-printed Appliance Control Board (see our 3D print designs Github repo)

After it's printed, I find the holes usually need to be reamed out with a 3.2mm (1/8") drill bit, otherwise the bolts don't fit through.

Step 2 - Attach Screw Terminal Blocks and Boards

Once the holes have been cleaned, it's time to start assembling the baseboard. First, using (4) 12mm M3 socket screws and (4) hex spacers, install "feet" on the corners of the board. This gives clearance on the board by raising it off the work surface. Then attach the terminal blocks as shown:

Next, attach the Netduino, half-size breadboard (it should have mounting tape on the back), and relay using the 12mm M3 socket screws and hex nuts as shown below:

Once the boards and terminal blocks are on, put some mounting tape on the power adapter, and remove backing. Make sure to put it on the correct side:

Then attach the power adapter to baseboard. Make sure the USB cable fits as follows:

Step 3 - Wire the Power Adapter In

Next, we want to wire the power adapter into our screw terminals. These screw terminals will be used to distribute our household electrical power (120V/240V). However, I've found that these screw terminals are meant to handle a little larger wire, so I recommend stripping and then soldering the end of the wire so it provides a more solid contact point:

It doesn't matter which wire goes to which screw terminal, as long as the wires are divided between the blocks. You can ignore the red wire above for now.

Step 4 - Add the DC Circuit Control Wires

Now we can add all the DC control circuit wires. The wiring for this is very simple; the relay requires power and ground and then a digital IO wire for each relay.

In this example, the breadboard is not actually needed, but by having it, we can add more complex circuits later. In the photo below, you can see that I’ve used male to male jumpers to wire the power rail (3.3V and GND) of the Netduino to the left power rail on the breadboard. This gives us a common power rail to add more circuits. I’ve also tied that into the relay with the red and orange wires. Note that it really doesn’t matter what colors of wire you use.

Finally, I’ve wired the Netduino digital IO pins 2 and 3 to the IN2 and IN1, respectively, on the relay board. In our case, we’ll actually only use one of the two relay channels available. Note that for the relay board, you’ll need male to female jumpers, since the relay exposes male pins.

Step 5 - Prepare the Appliance Cord

Next, we need to cut the plug off the coffee maker, strip the ends, and optionally, add a little solder:

Step 6 - Add our Household Electrical Power

Next, cut and strip the end of the extension cord. It's a good idea to make the Hot and Neutral sides, through in practice, with AC appliances, it almost never matters. For North American plugs the hot side is the smaller prong, and the Neutral side is the larger prong. For other plugs, refer to this Wikipedia article on AC power plugs and sockets.

Then, connect the household power extension cord to the terminal blocks. Each terminal block should get one of the wires. I've labeled the neutral and hot, but again, it's unnecessary 99.9% of the time:

Step 7 - Wire the Coffee Pot into the Circuit

The last thing we need to do to finish our circuit is to wire the coffee pot into the relay. A relay is an electromechanical switch that uses an electromagnet to physical move the switch. Relays are often used in setups like this because you can control larger and/or different types of current with a small DC current. In this case, we’re using 3.3V of DC to control a switch that controls 120V or 240V AC. For a more detailed discussion of how they work, see our relay guide.

The relay board that we’re using is a two channel relay board, meaning that it has two relays, to control two separate circuits. We’re only going to need one relay for now. For each relay, there are three screw terminals that correspond to the normally closed wire, the power wire, and the normally open wire. Normally closed and normally open refer to whether or not that side of the switch is connected to the center power wire when the relay is not powered. In this case, we need to connect the center terminal to the hot side of our household electrical terminal block, and then the normally open terminal to one of side of the coffee maker cord. The other wire of the coffee maker should then go to the neutral main screw terminal block.

The idea here is that when the relay is powered, it switches to connect the normally closed side to the power. This then creates a closed circuit through the coffee maker of neutral household main > coffee maker > normally closed terminal > hot household main:

When all the wiring is done, it should look something like the following:

Step 8 - Double-check the Wiring

Now that everything is wired up, it’s time to test our AC circuit to make sure that we don’t cause a short-circuit. While it’s unplugged from the wall, double-check that the extension cord wires are firmly in place with good connection and that they’re on different terminal blocks. Putting them on the same terminal block will cause a short-circuit and immediately cause the circuit breaker (or fuse) that your wall outlet is connected to, to trip. It may also cause sparks. we don’t want that.

Next, make sure that the coffee pot wires are also on different terminal blocks; one should be on neutral, and the other should connect to the hot terminal block, by way of the relay.

Finally, make sure that the USB adapter wires also go to different terminal blocks; one to the neutral and one to the hot.

After you’ve double-checked all those connections, plug the USB cable into the Netduino, and plug the extension cord into the wall outlet. If all is well, the Netduino and relay board should be powered. Unplug the extension cord from the wall, an unplug the USB cable from the Netduino. Next, we’re going to program the Netduino.

Step 9 - Test Control from Code

Plug the Netduino into your computer, launch Visual Studio, create a new .NET MicroFramework application called Connected_Coffee_SimpleControl, and add references to the following dlls:

  • Microsoft.SPOT.Hardware
  • System
  • SecretLabs.NETMF.Hardware.Netduino

Next, paste the following code in your program.cs file:

  1. using Microsoft.SPOT.Hardware;
  2. using SecretLabs.NETMF.Hardware.Netduino;
  3. using System.Threading;
  4.  
  5. namespace Connected_Coffee_SimpleControl
  6. {
  7. public class Program
  8. {
  9. public static void Main()
  10. {
  11. // create an output port (a port that can be written to) and
  12. // connect it to Digital Pin 2
  13. OutputPort relay = new OutputPort(Pins.GPIO_PIN_D2, false);
  14.  
  15. // run forever
  16. while (true)
  17. {
  18. relay.Write(true); // turn on the relay
  19. Thread.Sleep(5000); // Leave on for 5 seconds
  20. relay.Write(false); // turn off the relay
  21. Thread.Sleep(5000); // leave off for 5 seconds
  22. }
  23. }
  24. }
  25. }

This code will simply turn the coffee pot on for 5 seconds, then turn it off, and repeat. To test it, make sure the switch on the coffee pot is on, then plug the extension cord for the appliance control board into the wall and deploy the app. You should hear an audible “click” as the relay actuates, and the coffee maker light should come on. It’ll stay on for five seconds, and then turn off.

And once the program is deployed, it will run as long as the Netduino is plugged into power. So after deploying the program, you can plug the Netduino back into the USB power adapter, plug the extension cord back into the wall, and see it run:

Step 10 - Pat yourself on the back!

Congratulations!! You've now built a basic control circuit for a connected appliance! In the part 3 of this series, we're going to add the "connected" part of this project by adding a web API that runs on the Netduino so that we can control this remotely, from a web browser, or a mobile app!

Part 3: Introducing Maple Server

In part 2, we built the core of the connected coffee maker by creating what was essentially a smart power outlet that we could control with a Netduino. After assembling the hardware, we deployed an application that controlled our relay to to turn on household power to the coffee maker, effectively adding simple control.

In this entry part, we’re going to take this one step further and add a web API to the Netduino application so that we can control it remotely.

Once we have the web API in place, we will have an endpoint that can be taken advantage of from a variety of use cases. In fact, in the next part, we’ll build a Xamarin.Forms mobile application that uses that API to control the connected coffee pot from a mobile device:

The sample code for the entire connected coffee maker project can be found in the Netduino_Samples/Connected_CoffeeMaker repo. The code that runs on the Netduino is in the ApplianceHost app folder. That’s the code we’ll be examining here.

Introducing Maple Web Server

In order to expose the web API to allow remote control of our coffee maker, we need a web server to host it. So we’re introducing a purpose-built web server for Netduino; Maple Server.

Maple is an open source, ultra-lightweight, JSON enabled, RESTful web server built specifically for Netduino devices with network capability. It’s also published as a nuget package, so it’s incredibly easy to add to your projects. We purpose-built it for Netduino; it’s incredibly simple, fast, and super easy to use. It should run without issue on the N3 Ethernet, N3 Wifi, and N2+ models.

Request Handlers

Maple web API endpoints are defined by creating custom classes that inherit from RequestHandlerBase. Maple uses reflection to create urls based on the method names in those custom classes. It supports both the get and postverbs and method names must be prefixed with either one of those strings in order to be automatically made into an endpoint.

For example, the following RequestHandler class exposes three URL endpoints, /Status/TurnOn, and /TurnOff. As the method names indicate, the the Status endpoint accepts get requests, and the power control methods (TurnOn and TurnOff) are posts:

  1. using System;
  2. using Microsoft.SPOT;
  3. using Maple;
  4. using System.Net;
  5. using System.Collections;
  6. namespace ApplianceHost
  7. {
  8. public class RequestHandler : RequestHandlerBase
  9. {
  10. private static bool _isPowerOn;
  11. public RequestHandler(HttpListenerContext context) : base(context)
  12. {
  13. }
  14. public void getStatus()
  15. {
  16. StatusResponse();
  17. }
  18. public void postTurnOn()
  19. {
  20. TogglePower(true);
  21. StatusResponse();
  22. }
  23. public void postTurnOff()
  24. {
  25. TogglePower(false);
  26. StatusResponse();
  27. }
  28. private void TogglePower(bool val)
  29. {
  30. _isPowerOn = val;
  31. Ports.ONBOARD_LED.Write(val);
  32. Ports.GPIO_PIN_D1.Write(val);
  33. }
  34. private void StatusResponse()
  35. {
  36. this.Context.Response.ContentType = "application/json";
  37. this.Context.Response.StatusCode = 200;
  38. Hashtable result = new Hashtable {
  39. { "isPowerOn", _isPowerOn.ToString().ToLower() }
  40. };
  41. this.Send(result);
  42. }
  43. }
  44. }

When those endpoints are invoked, the appropriate method is called. In the case of our control server; the getStatus method returns a JSON formatted message containing the current on/off state of the relay, the postTurnOnmethod turns the relay on, and the postTurnOff method turns the relay off. postTurnOn and postTurnOff also keep the onboard LED in synch with the power to the relay as an indicator.

The Ports have been defined in the ports.cs class, which provide shortcuts to the OutputPort objects which represent the onboard LED, and digital pin 1, which controls the relay:

  1. using System;
  2. using Microsoft.SPOT;
  3. using Microsoft.SPOT.Hardware;
  4. using SecretLabs.NETMF.Hardware.Netduino;
  5. namespace ApplianceHost
  6. {
  7. static class Ports
  8. {
  9. static Ports()
  10. {
  11. ONBOARD_LED = new OutputPort(Pins.ONBOARD_LED, false);
  12. GPIO_PIN_D1 = new OutputPort(Pins.GPIO_PIN_D1, false);
  13. }
  14. public static OutputPort ONBOARD_LED;
  15. public static OutputPort GPIO_PIN_D1;
  16. }
  17. }

Using Maple, that’s all the code that’s needed to expose a modern, RESTful web API from a Netduino!

Network Initialization

Unlike traditional desktop or mobile applications in which the network interface has long been initialized by the time an app is run, you must first initialize the network interface and wait for it to get it’s IP address, etc., before attempting to do any network access. As such, before Maple Server is started, these tasks but be executed and waited on.

The bulk of the code in the main program.cs does just that; it initializes the network, waits for an IP address, and also makes a web request for validation purposes. Most of the code is dedicated to debug and informational output to illustrate the process and provide information for development-time exploration and instruction. It’s well-documented on the Netduino Networking guide, and we are working on shipping a nuget package that will handle all this stuff black-box, so in the future it’ll be even easier to add to your projects. As such, I’m not going to cover it in detail here, except to say that if you copy in the network initialization code into your own app, you’ll need to call the InitializeNetwork method and check it’s return (true on success) before you begin any processing that includes network access:

  1. if (InitializeNetwork())
  2. {
  3. // start the maple server
  4. // and start your application processing here
  5. }

Starting Maple Server

Once the network has been initialized, Maple Server needs to be instantiated and started:

  1. MapleServer server = new MapleServer();
  2. server.Start();

For most scenarios, this should go directly after the network initialization call, though, depending on your application needs, you might want to start it when needed.

Network Configuration

The final step necessary to setup the ApplicationHost sample is to configure the network. Some network pieces, such as the WiFi network name and password (if applicable), need to be configured at deploy time. If you’re developing on a Windows machine, you can use MFDeploy, which is installed as part of the .NET MicroFramework SDK. For Mac developers, we’ve created MacDeploy, which provides the same functionality:

If you’re using the Netduino 3 WiFi model, the authentication and encryption options can be a little confusing, however, if you’re connecting to a modern WiFi network that requires a password, you’ll likely need to set the Authenticationsetting to Shared, and the Encryption setting to WPA. Additionally, SSID refers to the name of the WiFi network.

Testing the Application/Control Server API

Once the network is configured and the application is deployed, it’s ready to test. If all goes well, the Application Output window in Visual Studio, should have something the following:

  1. Getting all the network interfaces.
  2. Found 802.11 WiFi Interface
  3. MAC Address: 60-D7-E3-A0-02-CB
  4. DHCP enabled: True
  5. Dynamic DNS enabled: False
  6. IP Address: 0.0.0.0
  7. Subnet Mask: 0.0.0.0
  8. Gateway: 0.0.0.0
  9. SSID:Cabin in the Woods
  10. Found 802.11 WiFi Interface
  11. No IP Address
  12. DHCP is enabled, attempting to get an IP Address
  13. Sleep while obtaining an IP
  14. Sleep while obtaining an IP
  15. Sleep while obtaining an IP
  16. Got IP Address: 172.16.42.8

You’ll need the IP address to test the API endpoint. The Status endpoint is easy to test via a browser; make sure you’re on the same network as the Netduino and open up a browser window and navigate to http://[IP Address]/Status. It should display a JSON response. However, I recommend getting Postman to test the endpoints. It’s free and designed specifically to test RESTful interfaces. It allows you to do POST requests in addition to GET, as well as a myriad of other useful things, including automatically parsing JSON responses:

Next Up – Mobile App

Stay tuned for more. In the next part, we’re going to build a Xamarin.Forms app to control our connected coffee maker from bed.

Part 4: Mobile App, Powered by Xamarin

In part 3, we enabled our connected coffee maker to be controlled via a Web API using Maple Server. In this part, we’re going to explore how to easily create a mobile app that runs on iOS, Android, and Windows, powered by Xamarin.Forms that connects to and controls the coffee maker remotely, from the palm of your hand

You can find the source code for the application in our Netduino_Samples repo.

Xamarin.Forms

Despite the fact that the app runs on iOS, Android, and Windows, it has very little code and is incredibly simple, owing to the fact that we built it in Xamarin.Forms.Xamarin.Forms is a technology that allows you to create native applications that run on multiple platforms using a single codebase. For many projects, virtually all of the code is shared between the platforms. Additionally, thanks to Microsoft, Xamarin.Forms is available for free via the Visual Studio Community Edition.

UI Code

The app has two screens; the home screen which displays the status of the connected coffee maker, and a button to turn it on and off, as well as a configure screen where you can enter the IP address of the appliance to control:

Home Page XAML

We’ve built the UI using XAML, a declarative UI markup language which makes complex layouts simple, and allows a clear separation between the page logic/functionality, and the element rendering.

Our homepage is nested in a ContentPage which provides automatic navigation. Xamarin.Forms will render elements as their native types on each platform, but we wanted to customize the look of our elements, so much of the code is sizing and color modifications. Additionally; we customized the navigation toolbar to add our “Configure” button using the ToolbarItemscollection:

We’ve built the UI using XAML, a declarative UI markup language which makes complex layouts simple, and allows a clear separation between the page logic/functionality, and the element rendering.

Our homepage is nested in a ContentPage which provides automatic navigation. Xamarin.Forms will render elements as their native types on each platform, but we wanted to customize the look of our elements, so much of the code is sizing and color modifications. Additionally; we customized the navigation toolbar to add our “Configure” button using the ToolbarItemscollection:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ApplianceRemote.StatusPage">
     <ContentPage.ToolbarItems>
         <ToolbarItem Text="Configure" Clicked="Configure_Clicked" />
     </ContentPage.ToolbarItems>
     <ContentPage.Content>
         <StackLayout>
             <Label x:Name="lblHeader" Text="Current Status" HorizontalOptions="Center"
                    FontSize="25" Margin="0, 20, 0, 0"></Label>
             <Label x:Name="lblStatus" HorizontalOptions="Center"></Label>
             <Button x:Name="btnAction" Clicked="Configure_Clicked" Margin="0,175,0,0"
                      Image="ConfigureAppliance.png" />
         </StackLayout>
     </ContentPage.Content>
 </ContentPage>

The code behind for this page is also very simple. We could have probably simplified even more by using Xamarin.Forms bindings, but for clarity, we’re manually setting the UI state and persisting back to our App object. The important methods here are OnAppearingConfigure_Clicked, and UpdateStatus:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Net.Http;
  5. using Newtonsoft.Json;
  6. using Newtonsoft.Json.Linq;
  7. using Xamarin.Forms;
  8. namespace ApplianceRemote
  9. {
  10. public partial class StatusPage : ContentPage
  11. {
  12. ApiHelper apiHelper;
  13. public StatusPage()
  14. {
  15. InitializeComponent();
  16. btnAction.CommandParameter = Commands.Configure;
  17. this.Title = "Connected Appliance";
  18. }
  19. async protected override void OnAppearing()
  20. {
  21. if (string.IsNullOrEmpty(App.HostAddress))
  22. {
  23. lblStatus.Text = "Not Connected";
  24. }
  25. else
  26. {
  27. apiHelper = new ApiHelper(App.HostAddress);
  28. lblStatus.Text = "Connecting to " + App.HostAddress;
  29. App.IsConnected = await apiHelper.Connect();
  30. if(App.IsConnected)
  31. {
  32. if (await apiHelper.CheckStatus())
  33. {
  34. App.ApplianceStatus = ApplianceStatus.On;
  35. }
  36. else
  37. {
  38. App.ApplianceStatus = ApplianceStatus.Off;
  39. }
  40. }
  41. UpdateStatus();
  42. }
  43. }
  44. async void Configure_Clicked(object sender, EventArgs e)
  45. {
  46. if(sender is Button)
  47. {
  48. var s = (Button)sender;
  49. if (s.CommandParameter.ToString() == Commands.Configure.ToString())
  50. {
  51. await Navigation.PushAsync(new ConfigurePage());
  52. }
  53. else if (s.CommandParameter.ToString() == Commands.TurnOn.ToString())
  54. {
  55. if (await apiHelper.TurnOn())
  56. {
  57. UpdateStatus();
  58. }
  59. }
  60. else if (s.CommandParameter.ToString()== Commands.TurnOff.ToString())
  61. {
  62. if (await apiHelper.TurnOff())
  63. {
  64. UpdateStatus();
  65. }
  66. }
  67. else
  68. {
  69. throw new ArgumentException();
  70. }
  71. }
  72. else
  73. {
  74. await Navigation.PushAsync(new ConfigurePage());
  75. }
  76. }
  77. void UpdateStatus()
  78. {
  79. if (!App.IsConnected)
  80. {
  81. lblStatus.Text = "Not Connected";
  82. btnAction.CommandParameter = Commands.Configure;
  83. btnAction.Image = "ConfigureAppliance.png";
  84. }
  85. else if (App.ApplianceStatus == ApplianceStatus.On)
  86. {
  87. lblStatus.Text = "On";
  88. btnAction.CommandParameter = Commands.TurnOff;
  89. btnAction.Image = "Stop.png";
  90. }
  91. else
  92. {
  93. lblStatus.Text = "Off";
  94. btnAction.CommandParameter = Commands.TurnOn;
  95. btnAction.Image = "Start.png";
  96. }
  97. }
  98. }
  99. public enum Commands{
  100. Configure,
  101. TurnOn,
  102. TurnOff
  103. }
  104. }

OnAppearing

OnAppearing is called just before the page is displayed to the user and presents an opportunity to update the screen with any new state information. In our case, we check to see if we’re connected to the appliance and display the appropriate connection and on/off state information.

Configured_Clicked

Both the toolbar Configure button, and the main button on the home page call the Configure_Clicked clicked method. First we check to see if it was a button or a toolbar item that called it. If the main button called it, we check the command state to see whether the coffee maker should be turned on or off, and then make the appropriate call, depending on that state. If the toolbar item called the method, then we simply push the configuration page on the navigation stack.

UpdateStatus

The UpdateStatus method is called by both OnAppearing and Configure_Clicked, and has two purposes; it updates the UI with the appliance state, and it keeps the command parameter in synch with the appliance state.

Configure Page XAML

The configure page allows us to set an IP of the connected appliance to communicate with:

It’s even simpler than the home page, and has a single entry for the IP address:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ApplianceRemote.ConfigurePage">
     <ContentPage.Content>
         <StackLayout Orientation="Horizontal" Padding="20,20,20,20">
             <StackLayout>
                 <Label Text="IP Address"></Label>
             </StackLayout>
             <StackLayout HorizontalOptions="EndAndExpand">
                 <Entry x:Name="IPAddressEntry" Placeholder="0.0.0.0"
                         Keyboard="Numeric" TextChanged="IPAddressEntry_TextChanged"
                         WidthRequest="150" />
             </StackLayout>
         </StackLayout>
     </ContentPage.Content>
 </ContentPage> 

Again, the code behind for this uses manual UI updates instead of binding for clarity:

  1. using System;
  2. using System.Collections.Generic;
  3. using Xamarin.Forms;
  4. namespace ApplianceRemote
  5. {
  6. public partial class ConfigurePage : ContentPage
  7. {
  8. public ConfigurePage()
  9. {
  10. InitializeComponent();
  11. IPAddressEntry.Text = App.HostAddress;
  12. }
  13. void IPAddressEntry_TextChanged(object sender, EventArgs e)
  14. {
  15. App.HostAddress = ((TextChangedEventArgs)e).NewTextValue;
  16. }
  17. }
  18. }

Web API Access Code

The final, and most important part of the code is the ApiHelper class, which is responsible for actually communicating with the Web API.

  1. using System;
  2. using

Code

3D print designs

Repository of 3D printable designs such as baseboards, enclosures, etc. for Netduino.

Netduino Sample: Connected Coffee Maker

Sample code for the entire connected coffee maker project.

Maple Server

Maple is an ultra-lightweight RESTful web server built specifically for network enabled Netduino devices. It's fully .NET MicroFramework 4.3 compatible and provides an easy to extend architecture.

Credits

Photo of Wilderness Labs

Wilderness Labs

Creators of Meadow. Makers of Netduino. We power connected things.

   

Leave your feedback...