Ok, thanks. It’s working pretty well, and I wanna share what I’ve got, so here are some of the unique parts. The only things to note are that I left out some of the long routines, and I made the _client variable global, and LastCommand is just tracking the last received message to compare to the new received message, timerInterval shuts down the motors if no message is received (the client application, upon connection, sends a regular heartbeat which resets the timer on each beat).
public static class Globals
{
static TimerCallback timerDelegate = new TimerCallback(CheckMotors.StopMotors);
public static Timer shutdownTimer = new Timer(timerDelegate, null, -1, -1);
public static int timerInterval = 5000;
public static double leftMotorSpeed, rightMotorSpeed;
public static double VELOCITY_RATE = 0.7;
public static double VELOCITY_EXPONENT = 0.7;
public static double VELOCITY_DIVISOR = 1;
public static double VELOCITY_STOP = 0;
public static string LastCommand = "";
public static Socket _client;
}
public class Program2
{
public static void Main()
{
Debug.EnableGCMessages(false);
//Debug.GC(true);
Thread.Sleep(3000); // wait for motor driver to settle
ClientConnection.InitializeMotordriver(); // initialize motor driver
FEZTouchDriver.LcdInit(); // initialize lcd screen
// Setup the network
//ethernet.UseStaticIP("192.168.0.101", "255.255.255.0", "192.168.0.1");
//Microsoft.SPOT.Net.NetworkInformation.NetworkInterface NI = Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0];
//NI.EnableStaticIP("192.168.1.4", "255.255.255.0", "192.168.1.1");
//
//byte[] mac = { 0x00, 0x26, 0x1C, 0x7B, 0x29, 0xE8 };
//WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10, (Cpu.Pin)FEZ_Pin.Digital.Di7, true);
//Dhcp.EnableDhcp(mac, "panda");
byte[] ip = { 192, 168, 1, 7 };
byte[] subnet = { 255, 255, 255, 0 };
byte[] gateway = { 192, 168, 1, 1 };
byte[] mac = { 0x00, 0x26, 0x1C, 0x7B, 0x29,0xE8 };
byte[] dns = { 192, 168, 1, 1 };
WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10,(Cpu.Pin)FEZ_Pin.Digital.Di7, true);
NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
NetworkInterface.EnableStaticDns(dns);
Debug.Print("Network settings:");
Debug.Print("IP Address: " + new IPAddress(NetworkInterface.IPAddress).ToString());
Debug.Print("Subnet Mask: " + new IPAddress(NetworkInterface.SubnetMask).ToString());
Debug.Print("Default Getway: " + new IPAddress(NetworkInterface.GatewayAddress).ToString());
Debug.Print("DNS Server: " + new IPAddress(NetworkInterface.DnsServer).ToString());
FEZTouchDriver.WriteLine(" ");
FEZTouchDriver.WriteLine("Network settings:");
FEZTouchDriver.WriteLine("IP Address: " + new IPAddress(NetworkInterface.IPAddress).ToString());
FEZTouchDriver.WriteLine("Subnet Mask: " + new IPAddress(NetworkInterface.SubnetMask).ToString());
FEZTouchDriver.WriteLine("Default Getway: " + new IPAddress(NetworkInterface.GatewayAddress).ToString());
FEZTouchDriver.WriteLine("DNS Server: " + new IPAddress(NetworkInterface.DnsServer).ToString());
// Start a new thread to listen for incomming connections
// I believe you can do exactly this in your main function
new Thread(() =>
{
// This code is running is a separate thread.
Socket socket1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint ep1 = new IPEndPoint(IPAddress.Any, 80);
socket1.Bind(ep1);
socket1.Listen(1);
Debug.Print("Main: Listening");
while (true)
{
// Wait for a client to connect
Socket client = socket1.Accept();
Debug.Print("Main: Client accepted");
// Client has connected, we hand it off to another thread to handle the client communication.
ClientConnection.Process(client);
}
}).Start();
Debug.Print("Main: Program Started");
FEZTouchDriver.WriteLine(" ");
FEZTouchDriver.WriteLine("Program Started");
}
}
class ClientConnection
{
private const int BufferSize = 1024;
//private Socket _client;
private byte[] _bytes = new byte[BufferSize];
private ByteBuffer _buffer = new ByteBuffer();
public static void Test()
{
//
}
public static void Process(Socket client)
{
ClientConnection connection = new ClientConnection(client);
connection.Start();
}
private ClientConnection(Socket client)
{
//_client = client;
Globals._client = client;
}
private void Start()
{
new Thread(ProcessData).Start();
}
private void SendMsg(string msg)
{
try
{
Byte[] sendBytes = Encoding.UTF8.GetBytes(msg);
//_client.Send(sendBytes);
Globals._client.Send(sendBytes);
}
catch (Exception exc)
{
Debug.Print("SendMsg: exception caught - " + exc);
}
finally
{
//
}
}
private void ProcessData()
{
State state = State.ReadLength;
byte messageLength = 0;
try{
while (true)
{
//int bytesReceived = _client.Receive(_bytes);
int bytesReceived = Globals._client.Receive(_bytes);
// If received 0 bytes the client gracefully shutdown and closed the socket
if (bytesReceived == 0) break;
for (int i = 0; i < bytesReceived; i++)
{
_buffer.Enqueue(_bytes[i]);
}
while (_buffer.Count > 0)
{
switch (state)
{
case State.ReadLength:
if (_buffer.Count >= 1)
{
messageLength = _buffer.Dequeue();
state = State.ReadMessage;
}
break;
case State.ReadMessage:
if (_buffer.Count >= messageLength)
{
byte[] messageBytes = new byte[messageLength];
_buffer.Dequeue(messageBytes);
//interpret received message
string receivedMsg = new string(Encoding.UTF8.GetChars(messageBytes));
receivedMsg = receivedMsg.ToUpper();
Debug.Print("ProcessData(" + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + "): " + receivedMsg);
//send acknowledgement
SendMsg("Server Ack: " + receivedMsg + "|");
//evaluate message
EvaluateMessage(receivedMsg);
state = State.ReadLength;
}
break;
}
}
}
}
catch (SocketException)
{
// Something went wrong reading the socket
// the client possibly lost connection or
// under when a non-graceful shutdown.
// Note: You might want to check for specific socket error codes here,
// but at this point there is something wrong so you might as well
// just log the error and terminate the connection (this will happen in the finally block)
Debug.Print("ProcessData: exception caught");
}
finally
{
// If we reach here the client is no longer connected so we
// can release our server-side resources
if (Globals._client != null) Globals._client.Close();
Debug.Print("ProcessData: client closed");
}
}
public class FEZTouchDriver
{
public static FEZ_Components.FEZTouchConsole lcdConsole;
public static void Write(string message)
{
lcdConsole.Write(message);
}
public static void WriteLine(string message)
{
lcdConsole.WriteLine(message);
}
public static void Init()
{
LcdInit();
}
public static void LcdInit()
{
FEZ_Components.FEZTouchConsole.LCDConfiguration lcd_config =
new FEZ_Components.FEZTouchConsole.LCDConfiguration(
FEZ_Pin.Digital.Di28, FEZ_Pin.Digital.Di20,
FEZ_Pin.Digital.Di22, FEZ_Pin.Digital.Di23,
new FEZ_Pin.Digital[8]
{
FEZ_Pin.Digital.Di51, FEZ_Pin.Digital.Di50,
FEZ_Pin.Digital.Di49, FEZ_Pin.Digital.Di48,
FEZ_Pin.Digital.Di47, FEZ_Pin.Digital.Di46,
FEZ_Pin.Digital.Di45, FEZ_Pin.Digital.Di44
}, FEZ_Pin.Digital.Di24, FEZ_Pin.Digital.Di26);
lcdConsole = new FEZ_Components.FEZTouchConsole(lcd_config,
ConsoleColor.White, ConsoleColor.Blue);
lcdConsole.Clear();
}
}
static public void InitializeMotordriver()
// Pre: Character "170" (= Binary 1010 1010) needs to be send over serial port to Sabertooth 2x5 motor driver so it can determine the baud rate.
// Post: Character "170" is send over the serial port to the Sabertooth 2x5 motor driver and Sabertooth has determined the baud rate
// Sabertooth 2x5A motor driver sets to right PWM therefore right motor speed.
{
byte motordriverInitialisationValue = 170;
SerialPort SerialCOM1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); // Set Serial port COM to 9600 Baud, No parity bit, 8 data bits and 1 stop bit. (8N1 protocol) (Pin2; on FEZ Domino board)
SerialCOM1.Open(); //Open the Serial Port for communication (.NetMF 4.1 requirement)
//SerialCOM1.WriteTimeout = 1000; //The WriteTimeout; makes shure it doesn't write forever (optional)
SerialCOM1.Write(new byte[] { motordriverInitialisationValue }, 0, 1); // transmit data array (of 1 items) to serial port.
Debug.Print("InitializeMotordriver: Value - " + motordriverInitialisationValue); //# Text for Visual studio 2010 .net debug output monitor
SerialCOM1.Close(); // Close serial port, after sending data.
}
private void EvaluateMessage(string receivedMsg).....
static public void DriveMotor(byte address, byte direction, byte motorspeed)............