No – no exception if I comment out the WebServer code. Exception is the same from earlier:
#### Exception System.Exception - 0x00000000 (5) ####
#### Message:
#### Gadgeteer.Modules.GHIElectronics.SerCam::ReadBytes [IP: 002f] ####
#### Gadgeteer.Modules.GHIElectronics.SerCam::ReadFrameBuffer [IP: 006b] ####
#### Gadgeteer.Modules.GHIElectronics.SerCam::UpdateStreaming [IP: 003a] ####
A first chance exception of type ‘System.Exception’ occurred in GTM.GHIElectronics.SerCam.dll
I updated the WebServer to spin off separate threads and refactored into classes as follows below (it couldn’t handle more than one simultaneous request as written), but I still get the same exception if I try to run both the Camera code and the server:
Program.cs:
using Gadgeteer.Modules;
namespace GadgeteerCamera
{
public partial class Program
{
private WebServer server;
private LcdConsole lcdConsole;
private StreamingCamera streamingCamera;
private void ProgramStarted()
{
InitializeLcd();
InitializeCamera();
InitializeWebServer();
}
private void InitializeLcd()
{
bool rotationEnabled = display_T43.SetLCDRotation(Module.DisplayModule.LCDRotation.Clockwise90Degrees);
this.lcdConsole = new LcdConsole(Resources.GetFont(Resources.FontResources.small), display_T43, true);
lcdConsole.WriteLine("Initializing LCD...");
lcdConsole.WriteLine("Rotation Enabled: " + rotationEnabled.ToString());
}
private void InitializeCamera()
{
lcdConsole.WriteLine("Initializing Camera...");
this.streamingCamera = new StreamingCamera(serCam, display_T43, button, lcdConsole);
}
private void InitializeWebServer()
{
lcdConsole.WriteLine("Initializing Web Server...");
this.server = new WebServer("http", 8080, 200, ethernet_ENC28.Interface, lcdConsole);
}
}
}
WebServer.cs:
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using GHI.Premium.Net;
using Microsoft.SPOT;
namespace GadgeteerCamera
{
public class WebServer
{
private const string MyIP = "192.168.1.202";
private Thread serverThread = null;
private readonly Queue responseQueue;
private string prefix;
private int port = 8080;
private int timeout = 200;
private ManualResetEvent networkAvailablityBlocking = null;
private EthernetENC28J60 ethernet;
private LcdConsole lcdConsole;
public WebServer(string prefix, int port, int timeout, EthernetENC28J60 ethernet, LcdConsole lcdConsole)
{
this.lcdConsole = lcdConsole;
this.responseQueue = new Queue();
this.prefix = prefix;
this.port = port;
this.timeout = timeout;
this.ethernet = ethernet;
this.InitializeWebServer();
this.serverThread = new Thread(() => RunServer());
this.serverThread.Start();
}
private void InitializeWebServer()
{
ethernet.Open();
NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet);
ethernet.CableConnectivityChanged += (o, args) => ConnectivityChanged(o, args);
ethernet.NetworkAddressChanged += (o, args) => NetworkAddressChanged(o, args, ethernet);
ethernet.NetworkInterface.EnableStaticIP(MyIP, "255.255.255.0", "192.168.1.1");
if (!ethernet.IsCableConnected)
{
networkAvailablityBlocking = new ManualResetEvent(false);
do
{
if (!ethernet.IsCableConnected)
{
lcdConsole.WriteLine("Ethernet cable is not connected.");
}
else
{
break;
}
} while (!networkAvailablityBlocking.WaitOne(5000, false));
}
while (Equals(IPAddress.GetDefaultLocalAddress(), IPAddress.Any))
{
lcdConsole.WriteLine("IP Address is not set.");
}
lcdConsole.WriteLine("IP address is set: " + ethernet.NetworkInterface.IPAddress);
}
private void NetworkAddressChanged(object sender, EventArgs e, EthernetENC28J60 ethernet)
{
lcdConsole.WriteLine("New address for the Ethernet Network Interface ");
lcdConsole.WriteLine("Is DhCp enabled: " + ethernet.NetworkInterface.IsDhcpEnabled);
lcdConsole.WriteLine("Is DynamicDnsEnabled enabled: " + ethernet.NetworkInterface.IsDynamicDnsEnabled);
lcdConsole.WriteLine("NetworkInterfaceType " + ethernet.NetworkInterface.NetworkInterfaceType);
lcdConsole.WriteLine("Network settings:");
lcdConsole.WriteLine("IP Address: " + ethernet.NetworkInterface.IPAddress);
lcdConsole.WriteLine("Subnet Mask: " + ethernet.NetworkInterface.SubnetMask);
lcdConsole.WriteLine("Default Getway: " + ethernet.NetworkInterface.GatewayAddress);
lcdConsole.WriteLine("Number of DNS servers:" + ethernet.NetworkInterface.DnsAddresses.Length);
for (var i = 0; i < ethernet.NetworkInterface.DnsAddresses.Length; i++)
{
lcdConsole.WriteLine("DNS Server " + i.ToString() + ":" + ethernet.NetworkInterface.DnsAddresses[i]);
}
lcdConsole.WriteLine("------------------------------------------------------");
}
private void ConnectivityChanged(object sender, EthernetENC28J60.CableConnectivityEventArgs e)
{
lcdConsole.WriteLine("Built-in Ethernet Cable is " + (e.IsConnected ? "Connected." : "Disconneced."));
if (e.IsConnected)
{
networkAvailablityBlocking.Set();
}
}
private void RunServer()
{
var listener = new HttpListener(this.prefix, this.port);
if (prefix == "https")
{
var serverCertAsString = Resources.GetString(Resources.StringResources.cert_device_microsoft_com);
var serverCertAsArray = Encoding.UTF8.GetBytes(serverCertAsString);
listener.HttpsCert = new X509Certificate(serverCertAsArray, "NetMF");
}
while (true)
{
try
{
if (!listener.IsListening)
{
listener.Start();
}
var context = listener.GetContext();
lock (responseQueue)
{
responseQueue.Enqueue(context);
}
var handleRequestThread = new Thread(() => HandleRequestThread());
handleRequestThread.Start();
}
catch (InvalidOperationException)
{
listener.Stop();
Thread.Sleep(200);
}
catch (ObjectDisposedException)
{
listener.Start();
}
catch
{
Thread.Sleep(200);
}
}
}
private void HandleRequestThread()
{
HttpListenerContext context = null;
try
{
lock (responseQueue)
{
context = (HttpListenerContext)responseQueue.Dequeue();
}
if (context != null)
{
var request = context.Request;
switch (request.HttpMethod.ToUpper())
{
case "GET":
ProcessClientGetRequest(context);
break;
case "POST":
ProcessClientPostRequest(context);
break;
}
}
}
catch (SocketException)
{
}
finally
{
if (context != null)
{
context.Close();
}
}
}
private void ProcessClientGetRequest(HttpListenerContext context)
{
var request = context.Request;
var response = context.Response;
var clientAddress = request.RemoteEndPoint.Address.ToString();
var user = request.UserAgent;
lcdConsole.WriteLine(clientAddress + " (" + user + ") " + request.HttpMethod.ToUpper()
+ ": " + request.RawUrl);
const string defaultMessage = "Welcome to the Brown Family internal website.";
var outBuffer = Encoding.UTF8.GetBytes(defaultMessage);
response.OutputStream.Write(outBuffer, 0, outBuffer.Length);
}
private void ProcessClientPostRequest(HttpListenerContext context)
{
throw new NotImplementedException();
}
}
}
StreamingCamera.cs:
using Gadgeteer.Modules.GHIElectronics;
using Microsoft.SPOT;
namespace GadgeteerCamera
{
public class StreamingCamera
{
private const int SampleRate = 100;
private SerCam serCam;
private Display_T43 display;
private Button button;
private LcdConsole lcdConsole;
private Bitmap lcd;
private bool cameraOn = true;
public StreamingCamera(SerCam serCam, Display_T43 display, Button button, LcdConsole lcdConsole)
{
this.serCam = serCam;
this.display = display;
this.button = button;
this.lcdConsole = lcdConsole;
InitializeCamera();
}
public void InitializeCamera()
{
// Setup timer and button events
var timer = new Gadgeteer.Timer(SampleRate, Gadgeteer.Timer.BehaviorType.RunContinuously);
// Setup timer and button events
timer.Tick += new Gadgeteer.Timer.TickEventHandler(SampleCamera);
button.ButtonPressed += new Button.ButtonEventHandler(ToggleCamera);
// Setup image resolution
lcd = new Bitmap((int) display.Width, (int) display.Height);
serCam.SetImageSize(SerCam.Camera_Resolution.SIZE_VGA);
// Start the timer and streaming
timer.Start();
serCam.StartStreaming();
lcdConsole.WriteLine("Streaming started...");
}
private void SampleCamera(Gadgeteer.Timer timer)
{
lcdConsole.WriteLine("Camera");
// If the camera is ready to stream a new image, then stream it
if (serCam.isNewImageReady && cameraOn)
{
lcdConsole.WriteLine("Drawing image...");
serCam.DrawImage(lcd, 0, 0, (int) display.Width, (int) display.Height);
display.SimpleGraphics.DisplayImage(lcd, 0, 0);
}
}
private void ToggleCamera(Button sender, Button.ButtonState state)
{
if (cameraOn)
{
lcdConsole.WriteLine("Streaming stopped");
display.SimpleGraphics.Clear();
cameraOn = false;
}
else
{
cameraOn = true;
}
}
}
}
LcdConsole.cs:
using System.Collections;
using Gadgeteer;
using Gadgeteer.Modules.GHIElectronics;
using Microsoft.SPOT;
namespace GadgeteerCamera
{
public class LcdConsole
{
private const int LineSpacing = 0;
private ArrayList screenText;
private Font font;
private Display_T43 display;
private int fontHeight;
private int fontWidth;
private int widthInCharacters;
private int lineHeight;
private int linesPerScreen;
private bool debugOutput;
public LcdConsole(Font font, Display_T43 display, bool debugOutput)
{
this.font = font;
this.display = display;
this.debugOutput = debugOutput;
this.fontHeight = this.font.Height;
this.fontWidth = this.font.AverageWidth + this.font.AverageWidth/2;
this.widthInCharacters = (int) (this.display.Width/this.fontWidth);
this.lineHeight = this.fontHeight + LineSpacing;
this.linesPerScreen = (int) (this.display.Height/this.lineHeight);
this.screenText = new ArrayList();
}
public void WriteLine(string line)
{
if (line.Length <= this.widthInCharacters)
{
screenText.Add(line);
}
else
{
var lineIndex = 0;
var lineLength = line.Length;
do
{
screenText.Add(lineLength <= this.widthInCharacters
? line.Substring(lineIndex, lineLength)
: line.Substring(lineIndex, this.widthInCharacters));
lineLength -= this.widthInCharacters;
lineIndex += this.widthInCharacters;
} while (lineLength > 0);
}
this.DisplayText();
if (debugOutput)
{
Debug.Print(line);
}
}
private void DisplayText()
{
if (this.screenText.Count <= this.linesPerScreen)
{
DrawScreen(0);
}
else
{
DrawScreen(screenText.Count - this.linesPerScreen);
}
}
private void DrawScreen(int arrayIndex)
{
uint whichLine = 0;
for (var i = arrayIndex; i < screenText.Count; i++)
{
this.display.SimpleGraphics.DisplayText(
(string) screenText[i],
font,
Color.White,
0,
whichLine);
whichLine += (uint) this.lineHeight;
}
}
}
}