Matthew Moses avatar Matthew Moses committed aad131b

Add code to read a complete scan.

Comments (0)

Files changed (3)

SerialPortTest/MainClass.cs

 
     public static class MainClass
     {
-        private const string PORT_NAME = "COM8";
         private const int BAUD_RATE = 9600;
-        private const Parity PARITY = Parity.None;
         private const int DATA_BITS = 8;
+        private const Parity PARITY = Parity.None;
+        private const string PORT_NAME = "COM8";
+        private const int READ_TIMEOUT = 100;
         private const StopBits STOP_BITS = StopBits.One;
 
         public static void Main(string[] args)
             try
             {
                 port = new SerialPort(PORT_NAME, BAUD_RATE, PARITY, DATA_BITS, STOP_BITS);
-                port.DataReceived += DataReceived;
+                port.ReadTimeout = READ_TIMEOUT;
                 port.ErrorReceived += ErrorReceived;
                 port.PinChanged += PinChanged;
+
+                PortHandler handler = new PortHandler(port);
+                handler.ReadComplete += ReadComplete;
+
                 port.Open();
 
                 Console.Out.WriteLine("You may press any key at any time to quit.");
             }
         }
 
+        static void ReadComplete(object sender, ReadCompleteEventArgs e)
+        {
+            if (e.Error != null)
+            {
+                Console.Out.WriteLine("A read was incomplete because of an error.");
+                Console.Error.WriteLine(e.Error);
+            }
+            else
+            {
+                Console.Out.WriteLine(string.Format(
+                    "Data was successfully read (length = {0}): \"{1}\"",
+                    e.Content.Length,
+                    Convert.ToBase64String(e.Content)));
+            }
+        }
+
         private static void PinChanged(object sender, SerialPinChangedEventArgs e)
         {
             Console.Out.WriteLine("PinChanged event: EventType = " + e.EventType);
         {
             Console.Out.WriteLine("ErrorReceived event: Event Type = " + e.EventType);
         }
-
-        private static void DataReceived(object sender, SerialDataReceivedEventArgs e)
-        {
-            Console.Out.WriteLine("DataReceived event: Event Type = " + e.EventType);
-        }
     }
 }

SerialPortTest/PortHandler.cs

+namespace Sti.IO.SerialPortTest
+{
+    using System;
+    using System.IO.Ports;
+
+    public sealed class PortHandler
+    {
+        private const int DEFAULT_BUFFER_SIZE = 256;
+        private const int BUFFER_RESIZE_THRESHOLD = 8;
+
+        public event EventHandler<ReadCompleteEventArgs> ReadComplete;
+
+        private byte[] buffer;
+        private int bufferIndex;
+        private readonly SerialPort port;
+
+        public PortHandler(SerialPort port)
+        {
+            if (port == null)
+                throw new ArgumentNullException("port");
+
+            this.buffer = new byte[DEFAULT_BUFFER_SIZE];
+            this.port = port;
+            this.port.DataReceived += DataReceived;
+        }
+
+        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
+        {
+            SerialPort port = (SerialPort)sender;
+            if (!port.IsOpen || e.EventType == SerialData.Eof)
+                return;
+
+            ReadCompleteEventArgs args = null;
+            ReadState state = ReadState.Reading;
+            while (port.IsOpen && state == ReadState.Reading)
+            {
+                if (buffer.Length - bufferIndex < BUFFER_RESIZE_THRESHOLD)
+                {
+                    byte[] bufferNew = new byte[buffer.Length + (buffer.Length / 2)];
+                    Buffer.BlockCopy(buffer, 0, bufferNew, 0, bufferIndex);
+                    buffer = bufferNew;
+                }
+
+                try
+                {
+                    bufferIndex += port.Read(buffer, bufferIndex, buffer.Length - bufferIndex);
+                }
+                catch (TimeoutException)
+                {
+                    state = ReadState.Complete;
+                    byte[] result = new byte[bufferIndex];
+                    Buffer.BlockCopy(buffer, 0, result, 0, bufferIndex);
+                    args = new ReadCompleteEventArgs(result);
+                }
+                catch (Exception ex)
+                {
+                    state = ReadState.Error;
+                    args = new ReadCompleteEventArgs(ex);
+                }
+            }
+
+            if (args != null && ReadComplete != null)
+                ReadComplete(this, args);
+        }
+
+        private enum ReadState
+        {
+            Reading,
+            Complete,
+            Error
+        }
+    }
+
+    public sealed class ReadCompleteEventArgs : EventArgs
+    {
+        private readonly byte[] content;
+        private readonly Exception error;
+
+        public ReadCompleteEventArgs(Exception error)
+        {
+            this.content = null;
+            this.error = error;
+        }
+
+        public ReadCompleteEventArgs(byte[] content)
+        {
+            this.content = content ?? new byte[0];
+            this.error = null;
+        }
+
+        public byte[] Content
+        {
+            get
+            {
+                if (this.error != null)
+                    throw new InvalidOperationException("No content was set because of an error.");
+                return this.content;
+            }
+        }
+
+        public Exception Error
+        {
+            get { return this.error; }
+        }
+    }
+}

SerialPortTest/SerialPortTest.csproj

   </ItemGroup>
   <ItemGroup>
     <Compile Include="MainClass.cs" />
+    <Compile Include="PortHandler.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.