I give you below a working demo in a Gadgeteer Cobra II board VS2010 NETMF 4.2 project with no external Gadgeteer modules. Here is the C# file Program.cs, a web page smartcardhome.htm, and a style sheet smartcard.css. You do not have a text paste code for html in the forum, so I used the CS code to past the web page text here. You will have to add smartcardhome.htm as a file resource named “smartcardhome” and smartcard.css as a file resource named “smartcardcss”, in Resources.resx. A web server is started at IP address 192.168.8.235. Browse to http://192.168.8.235/smartcardhome. Press the submit button, see the result, go back and press the submit button again, about 10 times. Watch what happens in the function “fixResponderText”. When the submit button is pressed, responder.Body.Text is null about half the time.
//Program.cs
using System;
using System.Text;
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.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.Net.NetworkInformation;
using Microsoft.SPOT.Hardware;
using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GHINET = GHI.Premium.Net;
using GHI.Hardware.G120;
using GHI.Premium.System;
namespace GadgeteerDemoWebApp
{
public partial class Program
{
private Hashtable WebPageList;
private WebPage HomePageData;
private WebPage CssPageData;
private HTTPServer webServer;
private NetworkConfigData netData;
private SystemConfigData systemData;
private GHINET.EthernetENC28J60 eth;
private Microsoft.SPOT.Net.NetworkInformation.NetworkInterface ni;
private AutoResetEvent CableConnectedEvent;
private static StringBuilder sb = new StringBuilder();
private static Object StringBuilderLock = new Object();
// This method is run when the mainboard is powered up or reset.
void ProgramStarted()
{
/*******************************************************************************************
Modules added in the Program.gadgeteer designer view are used by typing
their name followed by a period, e.g. button. or camera.
Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
button.ButtonPressed +=<tab><tab>
If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
timer.Tick +=<tab><tab>
timer.Start();
*******************************************************************************************/
ThreadStart starter = new ThreadStart(ProcessCommands);
Thread th = new Thread(starter);
th.Start();
// Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
Debug.Print("Program Started");
}
/// <summary>
/// Initialize objects, start the network interface, start the web server
/// </summary>
void ProcessCommands()
{
try
{
CableConnectedEvent = new AutoResetEvent(false);
//Set up data objects for the data entry fields on the web page
byte[] MacAddress = new byte[] { 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
string StaticIP = "192.168.8.235";
string NetMask = "255.255.255.0";
string GatewayAddress = "0.0.0.0";
string PrimaryDNS = "0.0.0.0";
string SecondaryDNS = "0.0.0.0";
string CloudIP = "0.0.0.0";
netData = new NetworkConfigData(MacAddress, StaticIP, NetMask, GatewayAddress, PrimaryDNS, SecondaryDNS, CloudIP);
string ModelNumber = "SCD10003";
string SerialNumber = "CWCSCD11234";
Guid DeviceHiveId = Guid.NewGuid();
Guid DeviceHiveKey = Guid.NewGuid();
systemData = new SystemConfigData(ModelNumber, SerialNumber, DeviceHiveId, DeviceHiveKey);
//Set up virtual web pages for the web server
WebPageList = new Hashtable();
HomePageData = new WebPage(Resources.GetString(Resources.StringResources.smartcardhome), "smartcardhome.htm", "text/html");
CssPageData = new WebPage(Resources.GetString(Resources.StringResources.smartcardcss), "smartcard.css", "text/css");
//Keys for the HashTable should be the URL paths to virtual web pages
WebPageList.Add("smartcardhome", HomePageData);
WebPageList.Add("smartcardhome.htm", HomePageData);
WebPageList.Add("index.htm", HomePageData);
WebPageList.Add("smartcard.css", CssPageData);
webServer = new HTTPServer(WebPageList);
webServer.webServer_WebEventHandler += new WebEvent.ReceivedWebEventHandler(WebEventHandler);
StartTCPIP();
webServer.StartServer(netData.StaticIP);
}
catch (Exception ex)
{
Debug.Print("Could not start program: " + ex.ToString() );
}
}
/// <summary>
/// Handle requests for web pages from the webServer object
/// </summary>
/// <param name="path">relative URL path to the page</param>
/// <param name="method">http method GET or POST</param>
/// <param name="responder">Responder class object</param>
public void WebEventHandler(string path, WebServer.HttpMethod method, Responder responder)
{
try
{
WebPage PageData = (WebPage)WebPageList[path];
string content = PageData.Content;
if (PageData.Url.ToLower() == "smartcardhome.htm")
{
if (method == WebServer.HttpMethod.POST)
{
content = webServer.fixResponderText(responder);
if (content == null)
{
content = "responder.Body.Text is null, cannot be fixed";
}
}
else if (method == WebServer.HttpMethod.GET)
{
if ((netData != null) && (systemData != null))
{
//replace placeholder text vertical bar in web page with the run-time text
//regular expressions are much too slow, use split function instead
string[] parts = content.Split(new char[] { '|' });
if (parts.Length == 9)
{
content = parts[0] + netData.MacAddress.ToHex()
+ parts[1] + netData.StaticIP
+ parts[2] + netData.NetMask
+ parts[3] + netData.GatewayAddress
+ parts[4] + netData.CloudIP
+ parts[5] + systemData.ModelNumber
+ parts[6] + systemData.SerialNumber
+ parts[7] + systemData.DeviceHiveId.ToString()
+ parts[8];
}
}
else
{
content = "memory cannot be read";
}
}
}
byte[] data = Encoding.UTF8.GetBytes(content);
responder.Respond(data, PageData.MimeType);
}
catch (Exception ex)
{
Debug.Print("WebEventReceived(): " + ex.ToString());
}
}
/// <summary>
/// Start the TCP/IP network interface
/// </summary>
/// <returns></returns>
private bool StartTCPIP()
{
bool rc = false;
eth = new GHINET.EthernetENC28J60(SPI.SPI_module.SPI2, Pin.P1_10, Pin.P2_11, Pin.P1_9, 4000);
eth.NetworkAddressChanged += new GHINET.NetworkInterfaceExtension.NetworkAddressChangedEventHandler(eth_NetworkAddressChanged);
eth.CableConnectivityChanged += new GHINET.EthernetENC28J60.CableConnectivityChangedEventHandler(eth_CableConnectivityChanged);
GHI.Premium.System.Util.SetMACAddress(GHI.Premium.System.NetworkInterface.ENC28j60_Ethernet, netData.MacAddress);
if (!eth.IsOpen) eth.Open();
if (!eth.IsCableConnected)
{
Debug.Print("Ethernet cable is not connected, waiting for connection");
CableConnectedEvent.WaitOne();
Thread.Sleep(1000);
}
ni = eth.NetworkInterface;
if (ni == null)
{
rc = false;
return rc;
}
//report MAC address settings
byte[] PhyAddress = netData.MacAddress;
string sMAC = BytesToHexString(PhyAddress, PhyAddress.Length);
Debug.Print("MAC address in flash memory = " + sMAC);
PhyAddress = ni.PhysicalAddress;
sMAC = BytesToHexString(PhyAddress, PhyAddress.Length);
Debug.Print("MAC address in Network Interface = " + sMAC);
//set IP, Gateway, DNS IPs
ni.EnableStaticIP(netData.StaticIP, netData.NetMask, netData.GatewayAddress);
ni.EnableStaticDns(new string[] { netData.PrimaryDNS, netData.SecondaryDNS });
GHINET.NetworkInterfaceExtension.AssignNetworkingStackTo(eth);
if (eth.IsActivated)
Debug.Print("EthernetENC28J60 is activated");
else
Debug.Print("EthernetENC28J60 is shut down");
if (eth.IsOpen)
Debug.Print("EthernetENC28J60 interface is open");
else
Debug.Print("EthernetENC28J60 interface is closed");
if (eth.IsCableConnected)
Debug.Print("EthernetENC28J60 cable is connected");
else
Debug.Print("EthernetENC28J60 cable is not connected");
int waitCount = 60;
bool niSet = false;
while ((waitCount > 0) && !niSet)
{
Thread.Sleep(1000);
waitCount--;
if ((ni.IPAddress == netData.StaticIP) && (ni.SubnetMask == netData.NetMask))
niSet = true;
}
if (niSet)
{
Debug.Print("EthernetENC28J60 IP address has been set: IP = " + ni.IPAddress + " Subnet mask = " + ni.SubnetMask);
rc = true;
}
else
{
Debug.Print("Could not set EthernetENC28J60 IP address");
rc = false;
}
return rc;
}
void eth_CableConnectivityChanged(object sender, GHINET.EthernetENC28J60.CableConnectivityEventArgs e)
{
try
{
if (e.IsConnected)
{
Debug.Print("PrototypeDevice.CableConnectivityChanged Event - Ethernet cable is connected");
CableConnectedEvent.Set();
}
else
{
Debug.Print("PrototypeDevice.CableConnectivityChanged Event - Ethernet cable is not connected");
}
}
catch (Exception ex)
{
Debug.Print("PrototypeDevice.eth_CableConnectivityChanged() exception " + ex.ToString());
}
}
void eth_NetworkAddressChanged(object sender, EventArgs e)
{
try
{
Microsoft.SPOT.Net.NetworkInformation.NetworkInterface ni = eth.NetworkInterface;
Debug.Print("NetworkAddressChanged Event");
if (ni.IsDhcpEnabled)
Debug.Print("DHCP is enabled");
else
Debug.Print("DHCP is disabled");
Debug.Print("IP address = " + ni.IPAddress);
Debug.Print("Gateway address = " + ni.GatewayAddress);
Debug.Print("Subnet mask = " + ni.SubnetMask);
foreach (string address in ni.DnsAddresses)
{
Debug.Print("DNS address = " + address);
}
}
catch (Exception ex)
{
Debug.Print("eth_NetworkAddressChanged() exception " + ex.ToString());
}
}
/// <summary>
/// Convert byte array to a ASCII-HEX character string
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string BytesToHexString(byte[] Data, int Count)
{
string rv = "";
try
{
lock (StringBuilderLock)
{
sb.Clear();
for (int i = 0; i < Count; i++)
{
sb.Append(Data[i].ToHex());
}
rv = sb.ToString();
}
}
catch (Exception ex)
{
Debug.Print("Exception in BytesToHexString(): " + ex.ToString());
}
return rv;
}
} //class Program
/// <summary>
/// TCP/IP network configuration
/// </summary>
public class NetworkConfigData
{
public byte[] MacAddress { get; set; }
public string StaticIP { get; set; }
public string NetMask { get; set; }
public string GatewayAddress { get; set; }
public string PrimaryDNS { get; set; }
public string SecondaryDNS { get; set; }
public string CloudIP { get; set; }
public NetworkConfigData(
byte[] _MacAddress,
string _StaticIP,
string _NetMask,
string _GatewayAddress,
string _PrimaryDNS,
string _SecondaryDNS,
string _CloudIP
)
{
MacAddress = _MacAddress;
StaticIP = _StaticIP;
NetMask = _NetMask;
GatewayAddress = _GatewayAddress;
PrimaryDNS = _PrimaryDNS;
SecondaryDNS = _SecondaryDNS;
CloudIP = _CloudIP;
}
}
/// <summary>
/// Device configuration data
/// </summary>
public class SystemConfigData
{
public string ModelNumber { get; set; }
public string SerialNumber { get; set; }
public Guid DeviceHiveId { get; set; }
public Guid DeviceHiveKey { get; set; }
public SystemConfigData(
string _ModelNumber,
string _SerialNumber,
Guid _DeviceHiveId,
Guid _DeviceHiveKey
)
{
ModelNumber = _ModelNumber;
SerialNumber = _SerialNumber;
DeviceHiveId = _DeviceHiveId;
DeviceHiveKey = _DeviceHiveKey;
}
}
public class WebPage
{
public string Content;
public string MimeType;
public string Url;
public WebPage(string _Content, string _Url, string _MimeType)
{
Content = _Content;
Url = _Url;
MimeType = _MimeType;
}
}
/// <summary>
/// This is our sample web server app project
/// </summary>
///
public class HTTPServer
{
private string ipAddress = "0.0.0.0";
private Hashtable WebPageList;
public event WebEvent.ReceivedWebEventHandler webServer_WebEventHandler;
public HTTPServer(Hashtable _WebPageList)
{
WebPageList = _WebPageList;
// create our web events
foreach (string key in WebPageList.Keys)
{
WebServer.SetupWebEvent(key).WebEventReceived += new WebEvent.ReceivedWebEventHandler(WebEventHandler);
}
}
/// <summary>
/// Send web events to the Business Logic module for handling
/// </summary>
/// <param name="path"></param>
/// <param name="method"></param>
/// <param name="responder"></param>
void WebEventHandler(string path, WebServer.HttpMethod method, Responder responder)
{
if (webServer_WebEventHandler != null)
{
webServer_WebEventHandler(path, method, responder);
}
}
public string fixResponderText(Responder responder)
{
string content = null;
if (responder.Body != null)
{
if (responder.Body.Text != null)
{
Debug.Print("responder.Body.Text is valid");
content = responder.Body.Text;
}
else
{
//random bug here - responder.Body.Text is null, but the
//responder.Body.RawContent byte array contains the text offset by many zeros
int len = responder.Body.RawContent.Length;
byte[] raw = new byte[len];
for (int i = 0, j = 0; i < len; i++)
{
if (responder.Body.RawContent[i] > 0)
{
raw[j] = responder.Body.RawContent[i];
j++;
}
}
if (raw.Length > 0)
{
content = new string(Encoding.UTF8.GetChars(raw));
Debug.Print("responder.Body.Text is null, I fixed it");
}
else
{
Debug.Print("responder.Body.Text is null, cannot be fixed");
}
}
}
return content;
}
/// <summary>
/// Start the server
/// </summary>
/// <param name="IPAddress"></param>
public bool StartServer(string _IPAddress)
{
ipAddress = _IPAddress;
WebServer.StartLocalServer(_IPAddress, 80);
Debug.Print("Web server started at: " + _IPAddress);
return true;
}
}
public static class ArrayHelpers
{
const string hexChars = "0123456789ABCDEF";
public static byte[] SkipAndTake(this byte[] array, int skip, int take)
{
byte[] result = new byte[take];
Array.Copy(array, skip, result, 0, take);
return result;
}
public static bool Compare(this byte[] array1, params byte[] array2)
{
int len1 = array1.Length;
if (len1 != array2.Length)
{
return false;
}
if (len1 == 0)
{
return true;
}
if (len1 > 256)
{
for (int i = 0; i < len1; i++)
{
if (array1[i] != array2[i])
{
return false;
}
}
}
else
{
for (byte i = 0; i < len1; i++)
{
if (array1[i] != array2[i])
{
return false;
}
}
}
return true;
}
public static String ToHex(this byte b)
{
return hexChars[b >> 4].ToString() + hexChars[b & 0x0F].ToString();
}
public static String ToHex(this byte[] data)
{
String s = "";
foreach (byte b in data)
{
s += b.ToHex();
}
return s;
}
public static String ToHex(this byte[] data, String spacer)
{
String s = "";
foreach (byte b in data)
{
if (s.Length > 0)
{
s += spacer;
}
s += b.ToHex();
}
return s;
}
public static String ToHex(this byte[] data, Char spacer)
{
String s = "";
foreach (byte b in data)
{
if (s.Length > 0)
{
s += spacer;
}
s += b.ToHex();
}
return s;
}
}
}
Smartcardhome.htm
<!DOCTYPE HTML PUBLIC "-//W3C/DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>CompuWeigh Corporation</title>
<meta name="keywords" content="Kiosk, SmartCard, Dispenser" />
<style type="text/css">
</style>
<link rel="stylesheet" type="text/css" href="smartcard.css"/>
</head>
<body>
<div id="masthead">
<h2 class="pagetitle">SmartCard Kiosk Configuration</h2>
</div>
<!-- <div id="topnav">
<a href="index.htm">Index</a>
<a href="tips.htm">Tips</a>
<a href="problems.htm">Problems</a>
<a href="products.htm">Products</a>
</div> -->
<div id="main">
<form method="post" enctype="application/x-www-form-urlencoded" action="smartcardhome">
<table>
<colgroup align="right" valign="top" width="200px"/>
<tr><td> </td></tr>
<tr>
<td>MacAddress:</td>
<td><input type="text" name="MacAddress" size="20" maxlength="12" value="|" /></td>
</tr>
<tr>
<td>IP address:</td>
<td><input type="text" name="IPAddress" size="20" value="|" maxlength="15" /></td>
</tr>
<tr>
<td>Subnet Mask:</td>
<td><input type="text" name="SubnetMask" size="20" value="|" maxlength="15" /></td>
</tr>
<tr>
<td>Gateway Address:</td>
<td><input type="text" name="GatewayAddress" size="20" value="|" maxlength="15" /></td>
</tr>
<tr>
<td>DeviceHive IP Address:</td>
<td><input type="text" name="HiveIPAddress" size="20" value="|" maxlength="15" /></td>
</tr>
<tr><td> </td></tr>
<tr>
<td>Model Number:</td>
<td><input type="text" name="ModelNumber" size="48" value="|" maxlength="30" /></td>
</tr>
<tr>
<td>Serial Number:</td>
<td><input type="text" name="SerialNumber" size="48" value="|" maxlength="30" /></td>
</tr>
<tr>
<td>Device Hive ID:</td>
<td><input type="text" name="DeviceHiveID" size="48" value="|" maxlength="36" /></td>
</tr>
<tr><td> </td></tr>
<tr>
<td></td>
<td><input type="submit" value="Submit" /> </td>
</tr>
</table>
</form>
</div>
</body>
</html>
smartcard.css
body {font-family: "Verdana", "Arial", "Helvetica", sans-serif}
hr {color: green; background-color: green; height: 3px; clear: left}
h1 {font-size: 26px}
h2 {font-size: 20px}
a:link {color: green}
a:visited {color: green}
a:hover {color: Red}
.pagetitle {font-size: 30px; margin: 0}
.tagline {margin: 2px}
.logo {float: left; margin: 5px; border: none; height: 45px}
table {border-style: none}
td {border-style: none; font-size: 13px;}
dl, p, li {font-size: 13px}
dt {font-weight: bold}
#masthead {background-color:Yellow; clear: left}
#topnav {padding-top: 15px;}
#bottomnav {background-color:Yellow; clear: left}
#copy {clear: left}