Character based serial communications are stubbornly difficult to program in theory. There are just too many little things that you don't think about when approaching the problem from a 'get the data, process the data' perspective. The possibilities are endless: What if the port stalls and returns no more data, what if there is a character missing in the expected data, etc. In many implementations these conditions will cause your code to completely lock up and go into an infinite loop. Although the SerialPort class of the .NET framework tries to present a clean interface, underneath this abstraction are still all the realities of serial communications.
You really need a reference implementation to even begin determining the quality parameters and pros and cons of your code ( if your concept even works at all ). Some things can be designed at a high level. Serial communications is not one of things. Get a machine, any machine that can meet the essential basic needs to create a WORKING proof of concept and go from there. What you probably want to aim for generally is something like the OSI protocol stack or TCP/IP stack. These stacks show how real robust MESSAGING system should be implemented. They include such essential features as error correction, retry aborted sessions, etc, etc. Although you may think these methods are overkill, you will find that implementing communications is not as simple as it seems, and the above mentioned messaging stacks have developed their complex nature in response to this challenging problem. Our own C-Sharp serial port class is presented below. It is far from perfect, but it's a start. using System; using System.IO.Ports; using System.Text; using System.Threading; namespace SerialPortSharp { public sealed class SerialPortConn : IDisposable { private readonly SerialPort serialPort; private readonly string returnToken; private readonly string hookOpen; private readonly string hookClose; private bool disposed; public SerialPortConn( string comPort = "Com1", int baud = 9600, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One, string returnToken = "> ", string hookOpen = "", string hookClose = "" ) { this.serialPort = new SerialPort(comPort, baud, parity, dataBits, stopBits) { ReadTimeout = 1000, RtsEnable = true, DtrEnable = true }; this.returnToken = returnToken; if (hookOpen == "") this.hookOpen = null; else this.hookOpen = hookOpen; if (hookClose == "") this.hookClose = null; else this.hookClose = hookClose; } public bool OpenConnection() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } try { this.serialPort.Open(); this.serialPort.DiscardInBuffer(); bool hooked = false; if (hookOpen != null) { hooked = this.Hook(); } else { hooked = true; } if (hooked) { return true; } else { return false; } } catch { return false; } } public bool CloseConnection() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } try { bool unhooked = false; if (hookClose != null) { unhooked = this.UnHook(); } else { unhooked = true; } if (unhooked) { Thread.Sleep(100); this.serialPort.ReadLine(); this.serialPort.DiscardInBuffer(); this.serialPort.Close(); this.serialPort.Dispose(); return true; } else { return false; } } catch { return false; } } public void Dispose() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot dispose of a disposed object."); } var closed = this.CloseConnection(); if (closed) { this.disposed = true; } else { throw new Exception("Error! Could not close port!"); } } private bool Hook() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } try { this.serialPort.Write(hookOpen + "\r"); Thread.Sleep(100); this.serialPort.DiscardInBuffer(); return true; } catch { return false; } } private bool UnHook() { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } try { this.serialPort.Write(hookClose + "\r"); Thread.Sleep(100); this.serialPort.DiscardInBuffer(); return true; } catch { return false; } } private string HookTest(string serialCommand) { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } try { this.serialPort.Write(serialCommand + "\r"); Thread.Sleep(100); bool loop = true; string output = ""; while (loop) { output += this.serialPort.ReadExisting(); if (output.EndsWith(this.returnToken)) { break; } } return output; } catch (TimeoutException e) { throw new Exception("Connection failed. Read timed out."); } } public string WriteConnection(string serialCommand, bool isSafe = false) { if (this.disposed) { throw new ObjectDisposedException(this.GetType().Name, "Cannot use a disposed object."); } if (isSafe) { var output = this.HookTest(serialCommand); return output; } else { try { this.serialPort.Write(serialCommand + "\r"); Thread.Sleep(100); return this.serialPort.ReadExisting(); } catch (Exception e) { throw new Exception("Connection failed. Timed out."); } } } } }
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories
All
|