First functional version complete.

This commit is contained in:
Edward Wright 2019-05-30 01:02:03 -04:00
parent 15e9103f7e
commit 3517c61f09

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports; using System.IO.Ports;
using System.Threading; using System.Threading;
@ -10,13 +8,11 @@ namespace SimplySerial
{ {
class SimplySerial class SimplySerial
{ {
static bool _continue = true; static SerialPort serialPort;
static SerialPort _serialPort;
// default comspec values and application settings set here will be overridden by values passed through command-line arguments
static bool Quiet = false; static bool Quiet = false;
static bool NoWait = false; static bool NoWait = false;
// default comspec values set here will be overridden by values passed through command-line arguments
static string port = string.Empty; static string port = string.Empty;
static int baud = 9600; static int baud = 9600;
static Parity parity = Parity.None; static Parity parity = Parity.None;
@ -25,55 +21,92 @@ namespace SimplySerial
static void Main(string[] args) static void Main(string[] args)
{ {
// process all command-line arguments
ProcessArguments(args); ProcessArguments(args);
ConsoleKeyInfo cki = new ConsoleKeyInfo(); // set up the serial port
Console.TreatControlCAsInput = true; serialPort = new SerialPort(port, baud, parity, dataBits, stopBits);
serialPort.Handshake = Handshake.None; // we don't need to support any handshaking at this point
serialPort.ReadTimeout = 1; // minimal timeout - we don't want to wait forever for data that may not be coming!
serialPort.WriteTimeout = 250; // small delay - if we go too small on this it causes System.IO semaphore timeout exceptions
serialPort.DtrEnable = true; // without this we don't ever receive any data
serialPort.RtsEnable = true; // without this we don't ever receive any data
string received = string.Empty; // this is where data read from the serial port will be temporarily stored
// attempt to open the serial port, terminate on error
_serialPort = new SerialPort("COM15", 9600, Parity.None, 8, StopBits.One); try
_serialPort.Handshake = Handshake.None;
_serialPort.ReadTimeout = 1; //Timeout.Infinite;
_serialPort.WriteTimeout = 250; //Timeout.Infinite;
_serialPort.DtrEnable = true;
_serialPort.RtsEnable = true;
byte[] buffer = new byte[_serialPort.ReadBufferSize];
string rx = string.Empty;
int bytesRead = 0;
_serialPort.Open();
//while (!_serialPort.IsOpen)
//Thread.Sleep(25);
while (_continue)
{ {
if (Console.KeyAvailable) serialPort.Open();
{ }
cki = Console.ReadKey(true); catch (System.UnauthorizedAccessException uae)
_serialPort.Write(Convert.ToString(cki.KeyChar)); {
} ExitProgram((uae.GetType() + " occurred while attempting to open the serial port. Is this serial port already in use in another application?"), exitCode: -1);
}
catch (Exception e)
{
ExitProgram((e.GetType() + " occurred while attempting to open the serial port."), exitCode: -1);
}
// set up keyboard input for relay to serial port
ConsoleKeyInfo keyInfo = new ConsoleKeyInfo();
Console.TreatControlCAsInput = true; // we need to use CTRL-C to activate the REPL in CircuitPython, so it can't be used to exit the application
// this is the core functionality - loop while the serial port is open
while (serialPort.IsOpen)
{
try try
{ {
//bytesRead = _serialPort.Read(buffer, 0, buffer.Length); // process keypresses for transmission through the serial port
rx = _serialPort.ReadExisting(); if (Console.KeyAvailable)
{
// determine what key is pressed (including modifiers)
keyInfo = Console.ReadKey(intercept: true);
} // exit the program if CTRL-X was pressed
catch (TimeoutException) if ((keyInfo.Key == ConsoleKey.X) && (keyInfo.Modifiers == ConsoleModifiers.Control))
{ {
serialPort.Close();
ExitProgram("\nSession terminated by user via CTRL-X.", exitCode: 0);
}
// properly process the backspace character
else if (keyInfo.Key == ConsoleKey.Backspace)
{
serialPort.Write("\b");
Thread.Sleep(150); // sort of cheating here - by adding this delay we ensure that when we process the receive buffer it will contain the correct backspace control sequence
}
// everything else just gets sent right on through
else
serialPort.Write(Convert.ToString(keyInfo.KeyChar));
}
// process data coming in from the serial port
received = serialPort.ReadExisting();
// if anything was received, process it
if (received.Length > 0)
{
// properly process backspace
if (received == ("\b\x1B[K"))
received = "\b \b";
// write what was received to console
Console.Write(received);
}
} }
//if (bytesRead > 0) catch (Exception e)
if (rx.Length > 0)
{ {
//rx = Encoding.ASCII.GetString(buffer, 0, bytesRead); ExitProgram((e.GetType() + " occurred while attempting to read/write to/from the serial port."), exitCode: -1);
Console.Write(rx);
} }
} }
_serialPort.Close();
// the serial port should be closed by now, but we'll make sure it is anyway
if (serialPort.IsOpen)
serialPort.Close();
// the program should have ended gracefully before now - there is no good reason for us to be here!
ExitProgram("\nSession terminated unexpectedly.", exitCode: -1);
} }
@ -83,14 +116,11 @@ namespace SimplySerial
/// <param name="args">Command-line parameters</param> /// <param name="args">Command-line parameters</param>
static void ProcessArguments(string[] args) static void ProcessArguments(string[] args)
{ {
// get a list of all available com ports
string[] availablePorts = SerialPort.GetPortNames();
// switch to lower case and remove '/', '--' and '-' from beginning of arguments - we can process correctly without them // switch to lower case and remove '/', '--' and '-' from beginning of arguments - we can process correctly without them
for (int i = 0; i < args.Count(); i++) for (int i = 0; i < args.Count(); i++)
args[i] = (args[i].TrimStart('/', '-')).ToLower(); args[i] = (args[i].TrimStart('/', '-')).ToLower();
// sort the parameters so that they get processed in order of priority (i.e. 'quiet' option gets processed before something that would normally result in console output) // sort the parameters so that they get processed in order of priority (i.e. 'quiet' option gets processed before something that would normally result in console output, etc.)
Array.Sort(args, new ArgumentSorter()); Array.Sort(args, new ArgumentSorter());
// iterate through command-line arguments // iterate through command-line arguments
@ -124,45 +154,69 @@ namespace SimplySerial
ExitProgram(("Invalid or incomplete argument <" + arg + ">\nTry 'SimplySerial help' to see a list of valid arguments"), exitCode: -1); ExitProgram(("Invalid or incomplete argument <" + arg + ">\nTry 'SimplySerial help' to see a list of valid arguments"), exitCode: -1);
} }
// com port // preliminary validate on com port, final validation occurs towards the end of this method
else if (argument[0].StartsWith("c")) else if (argument[0].StartsWith("c"))
{ {
string newPort = argument[1].ToUpper(); string newPort = argument[1].ToUpper();
if (!argument[1].StartsWith("COM")) if (!argument[1].StartsWith("COM"))
newPort = "COM" + argument[1]; newPort = "COM" + argument[1];
if (!availablePorts.Contains(newPort))
ExitProgram(("Cannot find specified port <" + newPort + ">"), exitCode: -1);
port = newPort; port = newPort;
Output("PORT: " + port);
} }
// baud rate // validate baud rate, terminate on error
else if (argument[0].StartsWith("b")) else if (argument[0].StartsWith("b"))
{ {
//validate requested baud rate // these are the baud rates we're supporting for now
Output("BAUD: " + argument[1]); string[] availableBaudRates = new string[] { "1200", "2400", "4800", "7200", "9600", "14400", "19200", "38400", "57600", "115200" };
if (availableBaudRates.Contains(argument[1]))
baud = Convert.ToInt32(argument[1]);
else
ExitProgram(("Invalid baud rate specified <" + argument[1] + ">"), exitCode: -1);
} }
// parity // validate parity, terminate on error
else if (argument[0].StartsWith("p")) else if (argument[0].StartsWith("p"))
{ {
//validate requested COM port if (argument[1].StartsWith("e"))
Output("PARITY: " + argument[1]); parity = Parity.Even;
else if (argument[1].StartsWith("m"))
parity = Parity.Mark;
else if (argument[1].StartsWith("n"))
parity = Parity.None;
else if (argument[1].StartsWith("o"))
parity = Parity.Odd;
else if (argument[1].StartsWith("s"))
parity = Parity.Space;
else
ExitProgram(("Invalid parity specified <" + argument[1] + ">"), exitCode: -1);
} }
// databits // validate databits, terminate on error
else if (argument[0].StartsWith("d")) else if (argument[0].StartsWith("d"))
{ {
//validate requested data bits int newDataBits = Convert.ToInt32(argument[1]);
Output("DATABITS: " + argument[1]);
if ((newDataBits > 3) && (newDataBits < 9))
dataBits = newDataBits;
else
ExitProgram(("Invalid data bits specified <" + argument[1] + ">"), exitCode: -1);
} }
// stopbits // validate stopbits, terminate on error
else if (argument[0].StartsWith("s")) else if (argument[0].StartsWith("s"))
{ {
//validate requested stop bits if (argument[1] == "0")
Output("STOPBITS: " + argument[1]); stopBits = StopBits.None;
else if (argument[1] == "1")
stopBits = StopBits.One;
else if (argument[1] == "1.5")
stopBits = StopBits.OnePointFive;
else if (argument[1] == "2")
stopBits = StopBits.Two;
else
ExitProgram(("Invalid stop bits specified <" + argument[1] + ">"), exitCode: -1);
} }
else else
{ {
@ -170,14 +224,21 @@ namespace SimplySerial
} }
} }
// default to the first/only available com port, exit with error if no ports are available // get a list of all available com ports
if (availablePorts.Count() >= 1) string[] availablePorts = SerialPort.GetPortNames();
SimplySerial.port = availablePorts[0];
else
ExitProgram("No COM ports detected.", exitCode: -1);
ExitProgram("That's All Folks!", exitCode: 1); // if no port was specified, default to the first/only available com port, exit with error if no ports are available
if (port == String.Empty)
{
if (availablePorts.Count() >= 1)
SimplySerial.port = availablePorts[0];
else
ExitProgram("No COM ports detected.", exitCode: -1);
}
else if (!availablePorts.Contains(port))
ExitProgram(("Invalid port specified <" + port + ">"), exitCode: -1);
// if we made it this far, everything has been processed and we're ready to proceed!
} }
@ -201,7 +262,7 @@ namespace SimplySerial
static void ExitProgram(string message="", int exitCode=0, bool silent=false) static void ExitProgram(string message="", int exitCode=0, bool silent=false)
{ {
if (!silent) if (!silent)
Output(message); Output("\n" + message);
if (!(SimplySerial.NoWait || silent)) if (!(SimplySerial.NoWait || silent))
{ {