Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Using UDP sockets to connect a Windows 8 Metro style app to a .NET Micro Framework device: Part 2

Pete Brown - 23 June 2012

In this post, I show how to set up the UDP code on the Micro Framework side so it can listen to messages coming from the Windows 8 app.

This is part 2 in a series of posts about using sockets to communicate between Windows 8 Metro apps and a microcontroller. The rest of the series may be found here:

The .NET Gadgeteer endpoint

Currently, you need Visual Studio 2010 to develop .NET Gadgeteer projects. If you have a Gadgeteer (or other .NET Micro Framework device) you probably already know that. So, set up a new .NET Gadgeteer Project named GadgeteerUdpDemo.

Module setup

As is typical, I've included the T35 display and the UsbClientDP modules in my circuit. The display is optional, but certainly helps for debugging or when you want to see the IP address on bootup. In addition, there's one MulticolorLed module and the ethernet module. The LED module is there to provide something for us to command, and the ethernet module is there to talk to the Windows 8 machine.

image

We won't use the LED in this post, but will in this overall project.

Setting the Gadgeteer device IP

I set the IP in code as well as on the device. Let me come right out and say that IP networking on the Gadgeteer is … troublesome. There are some bugs, and some inconsistent behavior. Therefore, I cover all the bases.

If your device hasn't picked up an IP, you may need to either clear out the old one, or hard-code a new one. Open up the .NET Micro Framework Deployment Tool (MFDeploy.exe) from the Tools folder in your .NET Micro Framework installation. Set the transport to USB, select the right device (EMX_Gadgeteer in my case) and ping the device. If it pings, then select "Configuration | Network" and set the static IP settings as appropriate for your network. You may be able to use DHCP - if so, great. I have a post explaining how to set up networking on the Gadgeteer which should help.

Use the MAC address provided with the board (should be on a sticker underneath). Don't use my MAC address, Subnet and gateway settings, but use settings for YOUR network. If you're not sure, run ipconfig /all from a command line on your PC and see what it gives you. That's a good starting point.

image

When set up, try pinging the device. The IP address of my Gadgeteer is 192.168.1.200

image

Keep working at this until you can ping the device and you get a return. Make sure your MAC address is correct, as MFDeploy likes to put a randomly generated one in there.

The point is to verify that the Gadgeteer device is successfully connected to the network and able to receive messages.

Main application code

To keep things demo (and proof-of-concept) simple, all the code is right in the main program. For my actual project, I'll refactor this out into a number of specialized classes. To set up the socket listener code, I started from the code in this codeplex project.

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;
using System.Net.Sockets;
using System.Net;

namespace GadgeteerUdpDemo
{
public partial class Program
{
// This method is run when the mainboard is powered up or reset.
void ProgramStarted()
{
Debug.Print("Program Started");

ethernet.UseStaticIP("192.168.1.200", "255.255.254.0", "192.168.1.1");

// required due to Gadgeteer bug where NetworkUp event
// doesn't fire on startup. Yes, this is brittle.
if (ethernet.IsNetworkUp)
{
Debug.Print("Network is up");
StartListener();
}
}

Socket _socket;
const int port = 5321;

Thread _listenerThread;

void StartListener()
{
Debug.Print("Starting listener");

_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

_listenerThread = new Thread(new ThreadStart(Listen));
_listenerThread.Start();
}

void OnDataReceived(byte[] data, int length, EndPoint sender)
{
// parse the command and light up the LED
Debug.Print("Data Received");

char[] text = new char[length];

for (int i = 0; i < length; i++)
{
text[i] = (char)data[i];
}

Debug.Print(new string(text));
}

private void Listen()
{
EndPoint endpoint = new IPEndPoint(IPAddress.Any, port);
_socket.Bind(endpoint);

while (true)
{
if (_socket.Poll(-1, SelectMode.SelectRead))
{
byte[] buffer = new byte[_socket.Available];

int length = _socket.ReceiveFrom(buffer, ref endpoint);

OnDataReceived(buffer, length, endpoint);
}
}
}
}
}

As I mentioned, the networking code in Gadgeteer is a bit buggy (or strange, I haven't decided which), so rather than use the helpful NetworkUp and NetworkDown events, I have to do a manual check. I don't like it, it has the potential for a race condition, but it works on my machine.

The code first sets up the same static IP address I entered in MFDeploy. Then, it checks to see if the network is up. If so, it starts a background thread which creates the Datagram/UDP socket and listens for incoming messages. When a message is received, the OnDataReceived method is executed. In there, I build a string and spit it out to the output window. Because I only check once, if the network doesn't come up, the code fails completely. Good enough for a demo.

Sending data from the Metro style app

In the previous post, I showed how to send data. We sent a simple "Hello!" message to port 5321 on another machine on the network. Now we'll need to change that to use the IP address and port set up on the Gadgeteer project. In my case, the Windows 8 Metro style app code looks like this:

private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
ni.Connect(new HostName("192.168.1.200"), "5321");
string cmd = "Hello!\r";

ni.SendMessage(cmd);
}

Make sure the IP address matches the one in the Gadgeteer code and the port number matches the port constant in the same code.

Run the Gadgeteer project in debug mode, and then after you see the listener on the board come up, press the "Connect and Send" button on the Windows 8 app. You should see something like the following in the Gadgeteer output window:

image

Note the "Data Received" and "Hello!" lines. That's data coming directly from the Windows 8 app, using UDP. Success!

Next steps

Once you have that working, you'll be ready to actually do some message processing and send something meaningful across the wire. The next step (in the next posts) will be to set up two-way communication and code up a simple protocol for turning the LED on and off.

           
posted by Pete Brown on Saturday, June 23, 2012
filed under:            

1 comment for “Using UDP sockets to connect a Windows 8 Metro style app to a .NET Micro Framework device: Part 2”

Comment on this Post

Remember me