using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.IO.Ports; using System.Windows.Forms; namespace SiWiComMSI { #region Public Enumerations public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error }; public enum PacketType { Error, Normal }; #endregion public partial class SiWiComDevTool_Main : Form { #region Local Variables // Various colors for logging info private Color[] LogMsgTypeColor = { Color.Gray, Color.LightGray, Color.Goldenrod, Color.Orange, Color.Red }; const int WM_NCLBUTTONDOWN = 0xA1; const int WM_NCHITTEST = 0x84; const int HT_CAPTION = 0x2; byte[] pcProtocolInputBuffer = new byte[8]; int pcProtocolByteCount = 0; int terminalCounter = 0; #endregion #region Constructor public SiWiComDevTool_Main() { InitializeComponent(); CheckForIllegalCrossThreadCalls = false; } #endregion #region Local Methods protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == WM_NCHITTEST) m.Result = (IntPtr)HT_CAPTION; } /// Save the user's settings. private void SaveSettings() { try { // If the port is open, close it. if (comport.IsOpen) comport.Close(); } catch (Exception) { } } /// Populate the form's controls with default settings. private void InitializeControlValues() { lstComPort.Items.Clear(); lstComPort.Height = 0; foreach (string s in SerialPort.GetPortNames()) { lstComPort.Items.Add(s); lstComPort.Height += 14; } if (lstComPort.Items.Count == 0) { MessageBox.Show(this, "No COM ports detected. \nYou need at least one free COM port for this to work!!!", "No COM ports detected!", MessageBoxButtons.OK, MessageBoxIcon.Error); this.Close(); } } /// Open serial port fom communication (9600bps). /// COM port to open. private void openComport(string port) { try { // If the port is open, close it. if (comport.IsOpen) comport.Close(); // Set the port's settings comport.BaudRate = 9600; comport.DataBits = 8; comport.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "1"); comport.Parity = (Parity)Enum.Parse(typeof(Parity), "None"); comport.PortName = port; // Open the port comport.Open(); btnConnect.ImageIndex = 1; } catch (Exception) { btnConnect.ImageIndex = 0; MessageBox.Show(this, "Error connecting to port! \nPlease check that no other program are connected to the selected COM port.", "Error connecting to port!", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// Adds one byte to the input buffer and validate packet when buffer is full. byte[] pcProtocolGetData() { pcProtocolByteCount = 0; return pcProtocolInputBuffer; } /// Adds one byte to the input buffer and validate packet when buffer is full. /// data byte to be added /// mode = MASTER or SLAVE /// specific address for the slave device bool pcProtocolAddByteToBuffer(byte data) { bool gotPacket = false; if (pcProtocolByteCount == 0) { if (data == 0x0A) { pcProtocolInputBuffer[pcProtocolByteCount] = data; pcProtocolByteCount++; } } else if (pcProtocolByteCount < pcProtocolInputBuffer.Length - 1) { pcProtocolInputBuffer[pcProtocolByteCount] = data; pcProtocolByteCount++; } else if (pcProtocolByteCount == pcProtocolInputBuffer.Length - 1) { pcProtocolInputBuffer[pcProtocolByteCount] = data; if (calculateChecksum(pcProtocolInputBuffer) == data) { gotPacket = true; } else { pcProtocolByteCount = 0; } } if (gotPacket) { return true; } else { return false; } } /// Calculate checksum for roboMSP packet. /// The packet to calculate on. /// Returns the checksum. private byte calculateChecksum(byte[] data) { int checksum = 0; for (int i = 0; i < (data.Length - 1); i++) { checksum += data[i]; } checksum &= 0x00FF; return (byte)checksum; } /// Extract command discription from roboMSP packet. /// The packet to extract from. /// Returns the command discription. private string getCommand(string stringToConvert) { switch (stringToConvert.Substring(3, 2)) { case "11": return "GET_DATA"; case "22": return "DATA"; case "33": return "DATA"; case "44": return "UPDATE"; case "55": return "UPDATE"; case "FE": return "ACK"; } return "Error"; } /// Extract id from roboMSP packet. /// The packet to extract from. /// Returns id. private string getId(string stringToConvert) { return stringToConvert.Substring(4, 2); } /// Send the user's data currently entered in the 'send' box. private void SendCommand(byte commandToSend, byte[] inputData) { byte[] data = { 0x0A, commandToSend, inputData[0], inputData[1], inputData[2], inputData[3], inputData[4], 0x55 }; data[data.Length - 1] = calculateChecksum(data); try { // Send the binary data out the port comport.Write(data, 0, data.Length); // Show the hex digits on in the terminal window Log(LogMsgType.Outgoing, ByteArrayToHexString(data), PacketType.Normal); } catch (Exception) { // Show the hex digits on in the terminal window //Log(LogMsgType.Outgoing, ByteArrayToHexString(data), PacketType.Error); } } /// Send ACK command to robot. /// Id to robot. private void SendACK() { byte[] data = { 0x0A, 0xFE, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; data[data.Length - 1] = calculateChecksum(data); try { comport.Write(data, 0, data.Length); // Show the hex digits on in the terminal window Log(LogMsgType.Outgoing, ByteArrayToHexString(data), PacketType.Normal); } catch (FormatException) { // Show the hex digits on in the terminal window //Log(LogMsgType.Outgoing, ByteArrayToHexString(data), PacketType.Error); } } /// Log data to the terminal window. /// The type of message to be written. /// The string containing the message to be shown. private void Log(LogMsgType msgtype, string msg, PacketType packetType) { if (packetType == PacketType.Error) { rtfTerminal.SelectedText = string.Empty; rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Regular); rtfTerminal.SelectionColor = LogMsgTypeColor[4]; rtfTerminal.AppendText("Error\n"); terminalCounter++; rtfTerminal.ScrollToCaret(); } else if (msgtype == LogMsgType.Incoming) { rtfTerminal.Invoke(new EventHandler(delegate { rtfTerminal.SelectedText = string.Empty; rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Regular); rtfTerminal.SelectionColor = LogMsgTypeColor[0]; rtfTerminal.AppendText(System.DateTime.Now.ToString("[HH:mm:ss]") + " >> "); rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Bold); rtfTerminal.SelectionColor = LogMsgTypeColor[0]; rtfTerminal.AppendText((msg) + " "); rtfTerminal.SelectedText = string.Empty; rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Regular); rtfTerminal.SelectionColor = LogMsgTypeColor[0]; rtfTerminal.AppendText((char)0x22 + getCommand(msg) + (char)0x22 + "\n"); terminalCounter++; rtfTerminal.ScrollToCaret(); })); } else if (msgtype == LogMsgType.Outgoing) { rtfTerminal.Invoke(new EventHandler(delegate { rtfTerminal.SelectedText = string.Empty; rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Regular); rtfTerminal.SelectionColor = LogMsgTypeColor[2]; rtfTerminal.AppendText(System.DateTime.Now.ToString("[HH:mm:ss]") + " << "); rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Bold); rtfTerminal.SelectionColor = LogMsgTypeColor[2]; rtfTerminal.AppendText((msg) + " "); rtfTerminal.SelectedText = string.Empty; rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Regular); rtfTerminal.SelectionColor = LogMsgTypeColor[2]; rtfTerminal.AppendText((char)0x22 + getCommand(msg) + (char)0x22 + "\n"); terminalCounter++; rtfTerminal.ScrollToCaret(); })); } if (terminalCounter == 300) { rtfTerminal.Clear(); terminalCounter = 0; } } /// Convert a string of hex digits (ex: E4 CA B2) to a byte array. /// The string containing the hex digits (with or without spaces). /// Returns an array of bytes. private void showDataOnPanel (byte[] data) { if ((data[1] == 0x22) || (data[1] == 0x33)) { decimal batTemp = Convert.ToDecimal((float)data[4] * 0.0146); decimal tempTemp = Convert.ToDecimal((float)data[3] / 9.8); decimal rssiTemp = Convert.ToDecimal((float)((sbyte)data[6]) / 2); lblAddr.Text = data[2].ToString(); lblBat.Text = Decimal.Round(batTemp, 1) + " V"; lblRSSI.Text = Decimal.Round(rssiTemp, 1) + " dB"; lblTemp.Text = Decimal.Round(tempTemp, 1) + " C"; } } /// Convert a string of hex digits (ex: E4 CA B2) to a byte array. /// The string containing the hex digits (with or without spaces). /// Returns an array of bytes. private byte[] HexStringToByteArray(string s) { s = s.Replace(" ", ""); byte[] buffer = new byte[s.Length / 2]; for (int i = 0; i < s.Length; i += 2) buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16); return buffer; } /// Converts an array of bytes into a formatted string of hex digits (ex: E4 CA B2) /// The array of bytes to be translated into a string of hex digits. /// Returns a well formatted string of hex digits with spacing. private string ByteArrayToHexString(byte[] data) { StringBuilder sb = new StringBuilder(data.Length * 3); foreach (byte b in data) sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' ')); return sb.ToString().ToUpper(); } /// Converts an array of bytes into a formatted string of hex digits (ex: E4 CA B2) /// The array of bytes to be translated into a string of hex digits. /// Returns a well formatted string of hex digits with spacing. private string ByteArrayToCharString(byte[] data) { StringBuilder sb = new StringBuilder(data.Length); foreach (byte b in data) sb.Append(Convert.ToChar(b)); return sb.ToString().ToUpper(); } #endregion #region Event Handlers private void Form1_Load(object sender, EventArgs e) { InitializeControlValues(); } #endregion private void comport_DataReceived(object sender, SerialDataReceivedEventArgs e) { // Obtain the number of bytes waiting in the port's buffer int bytes = comport.BytesToRead; byte[] buffer = new byte[bytes]; // Read the data from the port and store it in our buffer comport.Read(buffer, 0, bytes); //comport.DiscardInBuffer(); for (int i = 0; i < bytes; i++) { if (pcProtocolAddByteToBuffer(buffer[i])) { byte[] completePacket = pcProtocolGetData(); showDataOnPanel(completePacket); // Show the hex digits on in the terminal window Log(LogMsgType.Incoming, ByteArrayToHexString(completePacket), PacketType.Normal); } } } private void lstComPort_SelectedIndexChanged(object sender, EventArgs e) { openComport(lstComPort.Text); lstComPort.Visible = false; lblSelectPort.Visible = false; } private void SiWiComMSI_Main_FormClosing(object sender, FormClosingEventArgs e) { SaveSettings(); } private void btnClose_MouseEnter(object sender, EventArgs e) { btnClose.ImageIndex = 1; } private void btnClose_MouseLeave(object sender, EventArgs e) { btnClose.ImageIndex = 0; } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } private void btnConnect_Click_1(object sender, EventArgs e) { lstComPort.Visible = true; lblSelectPort.Visible = true; } private void lblLocalDeviceAddr_Click(object sender, EventArgs e) { listLocalDeviceAddr.Visible = true; } private void lblLocalMasterAddr_Click(object sender, EventArgs e) { listLocalMasterAddr.Visible = true; } private void lblRemoteOldDeviceAddr_Click(object sender, EventArgs e) { listRemoteOldDeviceAddr.Visible = true; } private void lblRemoteNewDeviceAddr_Click(object sender, EventArgs e) { listRemoteNewDeviceAddr.Visible = true; } private void lblRemoteMasterAddr_Click(object sender, EventArgs e) { listRemoteMasterAddr.Visible = true; } private void listLocalDeviceAddr_SelectedIndexChanged(object sender, EventArgs e) { listLocalDeviceAddr.Visible = false; lblLocalDeviceAddr.Text = listLocalDeviceAddr.Text; } private void listLocalMasterAddr_SelectedIndexChanged(object sender, EventArgs e) { listLocalMasterAddr.Visible = false; lblLocalMasterAddr.Text = listLocalMasterAddr.Text; } private void listRemoteMasterAddr_SelectedIndexChanged(object sender, EventArgs e) { listRemoteMasterAddr.Visible = false; lblRemoteMasterAddr.Text = listRemoteMasterAddr.Text; } private void listRemoteNewDeviceAddr_SelectedIndexChanged(object sender, EventArgs e) { listRemoteNewDeviceAddr.Visible = false; lblRemoteNewDeviceAddr.Text = listRemoteNewDeviceAddr.Text; } private void listRemoteOldDeviceAddr_SelectedIndexChanged(object sender, EventArgs e) { listRemoteOldDeviceAddr.Visible = false; lblRemoteOldDeviceAddr.Text = listRemoteOldDeviceAddr.Text; } private void btnSendLocal_Click(object sender, EventArgs e) { byte[] tmpPacket = { (byte)Convert.ToByte(lblLocalMasterAddr.Text), (byte)Convert.ToByte(lblLocalDeviceAddr.Text), (byte)Convert.ToByte(txtLocalWakeUpTime.Text), 0x00, 0x55 }; SendCommand(0x44, tmpPacket); lblLocalMasterAddr.Text = "0"; lblLocalDeviceAddr.Text = "0"; txtLocalWakeUpTime.Text = "0"; } private void btnSendRemote_Click(object sender, EventArgs e) { byte[] tmpPacket = { (byte)Convert.ToByte(lblRemoteOldDeviceAddr.Text), (byte)Convert.ToByte(lblRemoteMasterAddr.Text), (byte)Convert.ToByte(lblRemoteNewDeviceAddr.Text), (byte)Convert.ToByte(txtRemoteWakeUpTime.Text), 0x55 }; SendCommand(0x55, tmpPacket); lblRemoteOldDeviceAddr.Text = "0"; lblRemoteMasterAddr.Text = "0"; lblRemoteNewDeviceAddr.Text = "0"; txtRemoteWakeUpTime.Text = "0"; } private void btnIDLE_Click(object sender, EventArgs e) { byte[] tmpPacket = { 0x00, 0x00, 0x00, 0x01, 0x55 }; SendCommand(0x44, tmpPacket); } private void btnMASTER_Click(object sender, EventArgs e) { byte[] tmpPacket = { 0x00, 0x00, 0x00, 0x02, 0x55 }; SendCommand(0x44, tmpPacket); } private void btnSLAVE_Click(object sender, EventArgs e) { byte[] tmpPacket = { 0x00, 0x00, 0x00, 0x03, 0x55 }; SendCommand(0x44, tmpPacket); } private void btnNOICEMAKER_Click(object sender, EventArgs e) { byte[] tmpPacket = { 0x00, 0x00, 0x00, 0x04, 0x55 }; SendCommand(0x44, tmpPacket); } private void btnGetLocalData_Click(object sender, EventArgs e) { byte[] tmpPacket = { 0x55, 0x55, 0x55, 0x55, 0x55 }; SendCommand(0x11, tmpPacket); } } }