Merge pull request #25 from fasteddy516/unicode-support

Unicode support
This commit is contained in:
Edward Wright 2023-02-16 12:05:33 -05:00 committed by GitHub
commit 0e1b4b6e8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 316 additions and 63 deletions

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT Type="Advanced Installer" CreateVersion="16.0" version="18.8.1" Modules="simple" RootPath="." Language="en" Id="{9BAEE6C8-7726-40BA-ADC1-9001E7BBCAF9}">
<DOCUMENT Type="Advanced Installer" CreateVersion="16.0" version="20.3.2" Modules="simple" RootPath="." Language="en" Id="{9BAEE6C8-7726-40BA-ADC1-9001E7BBCAF9}">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="AI_CURRENT_YEAR" Value="2022" ValueLocId="-"/>
<ROW Property="AI_CURRENT_YEAR" Value="2023" ValueLocId="-"/>
<ROW Property="AI_PACKAGING_TOOL" Value="Advanced Installer 20.3.2 build 850835f9" ValueLocId="-"/>
<ROW Property="AI_PREDEF_LCONDS_PROPS" Value="AI_DETECTED_DOTNET_VERSION"/>
<ROW Property="AI_PROPPATH_DIR_PERBUILD_Newtonsoft.Json.dll" Value="..\SimplySerial\packages\Newtonsoft.Json.13.0.1\lib\net45"/>
<ROW Property="AI_PROPPATH_DIR_PERBUILD_boards.json_1" Value="..\SimplySerial\bin\Release"/>
@ -21,10 +22,10 @@
<ROW Property="ARPURLINFOABOUT" Value="https://github.com/fasteddy516/SimplySerial"/>
<ROW Property="ARPURLUPDATEINFO" Value="https://github.com/fasteddy516/SimplySerial/releases"/>
<ROW Property="Manufacturer" Value="fasteddy516"/>
<ROW Property="ProductCode" Value="1033:{9E648CE1-01C5-4E90-BFC7-05E709BB0F46} " Type="16"/>
<ROW Property="ProductCode" Value="1033:{0D848E26-A1D0-4E43-8332-8004B7867CC3} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="SimplySerial"/>
<ROW Property="ProductVersion" Value="0.7.2" Type="32"/>
<ROW Property="ProductVersion" Value="0.7.3"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{6A3965D3-95B6-4145-8B3C-6F55E2A16C31}"/>
<ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
@ -89,6 +90,7 @@
<ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
<ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
<ROW Fragment="Themes.aip" Path="&lt;AI_FRAGS&gt;Themes.aip"/>
<ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
<ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
<ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
@ -144,6 +146,7 @@
<ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_PRESERVE_INSTALL_TYPE" Type="65" Source="aicustact.dll" Target="PreserveInstallType"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
@ -176,6 +179,7 @@
<ROW Action="AI_DpiContentScale" Sequence="52"/>
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
<ROW Action="AI_DetectSoftware" Sequence="101"/>
<ROW Action="AI_PRESERVE_INSTALL_TYPE" Sequence="199"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType = 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
@ -187,7 +191,10 @@
<ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="Manufacturer" Root="-1" Key="Software\[Manufacturer]" Name="\"/>
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="ProductName" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="\"/>
<ROW Registry="Software" Root="-1" Key="Software" Name="\"/>
<ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT Type="Advanced Installer" CreateVersion="16.0" version="18.8.1" Modules="simple" RootPath="." Language="en" Id="{813739C4-1EBF-4720-9196-4AC91588D7AC}">
<DOCUMENT Type="Advanced Installer" CreateVersion="16.0" version="20.3.2" Modules="simple" RootPath="." Language="en" Id="{813739C4-1EBF-4720-9196-4AC91588D7AC}">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="AI_CURRENT_YEAR" Value="2022" ValueLocId="-"/>
<ROW Property="AI_CURRENT_YEAR" Value="2023" ValueLocId="-"/>
<ROW Property="AI_PACKAGING_TOOL" Value="Advanced Installer 20.3.2 build 850835f9" ValueLocId="-"/>
<ROW Property="AI_PREDEF_LCONDS_PROPS" Value="AI_DETECTED_DOTNET_VERSION"/>
<ROW Property="AI_PROPPATH_DIR_PERBUILD_Newtonsoft.Json.dll" Value="..\SimplySerial\packages\Newtonsoft.Json.13.0.1\lib\net45"/>
<ROW Property="AI_PROPPATH_DIR_PERBUILD_boards.json" Value="..\SimplySerial\bin\Release"/>
@ -21,10 +22,10 @@
<ROW Property="ARPURLINFOABOUT" Value="https://github.com/fasteddy516/SimplySerial"/>
<ROW Property="ARPURLUPDATEINFO" Value="https://github.com/fasteddy516/SimplySerial/releases"/>
<ROW Property="Manufacturer" Value="fasteddy516"/>
<ROW Property="ProductCode" Value="1033:{A7D68EA4-86D5-4918-9A4D-B5B7414184D4} " Type="16"/>
<ROW Property="ProductCode" Value="1033:{F6ED6598-FD70-489F-9805-64684160B29E} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="SimplySerial"/>
<ROW Property="ProductVersion" Value="0.7.2" Type="32"/>
<ROW Property="ProductVersion" Value="0.7.3"/>
<ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{64061592-EDD5-474E-B846-4CA070788BBE}"/>
@ -90,6 +91,7 @@
<ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
<ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
<ROW Fragment="Themes.aip" Path="&lt;AI_FRAGS&gt;Themes.aip"/>
<ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
<ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
<ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
@ -145,6 +147,7 @@
<ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_PRESERVE_INSTALL_TYPE" Type="65" Source="aicustact.dll" Target="PreserveInstallType"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
@ -177,6 +180,7 @@
<ROW Action="AI_DpiContentScale" Sequence="52"/>
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
<ROW Action="AI_DetectSoftware" Sequence="101"/>
<ROW Action="AI_PRESERVE_INSTALL_TYPE" Sequence="199"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 600) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 601) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 602) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 603) OR (MsiNTProductType = 1)) AND ((VersionNT64 &lt;&gt; 1000) OR (MsiNTProductType = 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
@ -188,7 +192,10 @@
<ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="Manufacturer" Root="-1" Key="Software\[Manufacturer]" Name="\"/>
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="ProductName" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="\"/>
<ROW Registry="Software" Root="-1" Key="Software" Name="\"/>
<ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

View File

@ -66,11 +66,19 @@ If you have multiple COM ports, multiple CircuitPython devices connected, or nee
`-a, --autoconnect` sets the desired auto-(re)connect behaviour (ex. `a:NONE`, `--autoconnect:ANY`)
`-l, --log` Logs all output to the specified file. (ex. `-l:ss.log`, `-log:"C:\Users\My Name\my log.txt"`)
`-l, --log` logs all output to the specified file (ex. `-l:ss.log`, `-log:"C:\Users\My Name\my log.txt"`)
`--logmode` Instructs SimplySerial to either `APPEND` to an existing log file, or `OVERWRITE` an existing log file. In either case, if the specified log file does not exist, it will be created. If neither option is specified, `OVERWRITE` is assumed. (ex. `--logmode:APPEND`)
`--logmode` instructs SimplySerial to either `APPEND` to an existing log file, or `OVERWRITE` an existing log file. In either case, if the specified log file does not exist, it will be created. If neither option is specified, `OVERWRITE` is assumed. (ex. `--logmode:APPEND`)
`-q, --quiet` prevents any application messages (connection banner, error messages, etc.) from printing out to the console.
`-q, --quiet` prevents any application messages (connection banner, error messages, etc.) from printing out to the console
`-f, --forcenewline` replaces carriage returns with linefeeds in received data
`-e, --encoding` sets the encoding to use when outputting to the terminal and log files. Defaults to `UTF8`, can also be set to `ASCII` (the default in SimplySerial versions prior to 0.8.0) or `RAW`. In `RAW` mode, all non-printable characters are displayed as `[xx]` where `xx` is the hexadecimal byte value of the character.
`-noc --noclear` don't clear the terminal screen on connection
`-nos --nostatus` block status/title updates generated by virtual terminal sequences (such as the CircuitPython status bar introduced in CP version 8.0.0)
If you wanted to connect to a device on COM17 at 115200 baud, you would use the command `ss -c:17 -b:115200`, or if you really enjoy typing `ss --com:17 --baud:115200`.

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("fasteddy516")]
[assembly: AssemblyProduct("SimplySerial")]
[assembly: AssemblyCopyright("Copyright © 2019 Edward Wright (fasteddy516)")]
[assembly: AssemblyCopyright("Copyright © 2023 Edward Wright (fasteddy516)")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -1,20 +1,20 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Threading;
using System.Linq;
using System.Management;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
namespace SimplySerial
{
class SimplySerial
{
const string version = "0.8.0-alpha.2";
const string version = "0.8.0-beta.1";
private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
@ -52,6 +52,10 @@ namespace SimplySerial
static int bufferSize = 102400;
static DateTime lastFlush = DateTime.Now;
static bool forceNewline = false;
static Encoding encoding = Encoding.UTF8;
static bool convertToPrintable = false;
static bool clearScreen = true;
static bool noStatus = false;
// dictionary of "special" keys with the corresponding string to send out when they are pressed
static Dictionary<ConsoleKey, String> specialKeys = new Dictionary<ConsoleKey, String>
@ -82,32 +86,37 @@ namespace SimplySerial
static void Main(string[] args)
{
// attempt to enable virtual terminal escape sequence processing
try
{
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(iStdOut, out uint outConsoleMode);
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(iStdOut, outConsoleMode);
}
catch
{
// if the above fails, it doesn't really matter - it just means escape sequences won't process nicely
}
// load and parse data in boards.json
LoadBoards();
// process all command-line arguments
ProcessArguments(args);
// attempt to enable virtual terminal escape sequence processing
if (!convertToPrintable)
{
try
{
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(iStdOut, out uint outConsoleMode);
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(iStdOut, outConsoleMode);
}
catch
{
// if the above fails, it doesn't really matter - it just means escape sequences won't process nicely
}
}
Console.OutputEncoding = encoding;
// verify log-related settings
if (logging)
{
try
{
{
FileStream stream = new FileStream(logFile, logMode, FileAccess.Write);
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
using (StreamWriter writer = new StreamWriter(stream, encoding))
{
writer.WriteLine($"\n----- LOGGING STARTED ({DateTime.Now}) ------------------------------------");
}
@ -118,7 +127,7 @@ namespace SimplySerial
ExitProgram($"* Error accessing log file '{logFile}'\n > {e.GetType()}: {e.Message}", exitCode: -1);
}
}
// set up keyboard input for program control / 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
@ -199,7 +208,8 @@ namespace SimplySerial
ReadTimeout = 1, // minimal timeout - we don't want to wait forever for data that may not be coming!
WriteTimeout = 250, // small delay - if we go too small on this it causes System.IO semaphore timeout exceptions
DtrEnable = true, // without this we don't ever receive any data
RtsEnable = true // without this we don't ever receive any data
RtsEnable = true, // without this we don't ever receive any data
Encoding = encoding
};
// attempt to set the baud rate, fail if the specified value is not supported by the hardware
@ -212,7 +222,7 @@ namespace SimplySerial
else
baud = 9600;
}
serialPort.BaudRate = baud;
}
catch (ArgumentOutOfRangeException)
@ -247,11 +257,20 @@ namespace SimplySerial
continue;
}
Console.Title = $"{port.name}: {port.board.make} {port.board.model}";
// if we get this far, clear the screen and send the connection message if not in 'quiet' mode
Console.Clear();
if (clearScreen)
{
Console.Clear();
}
else
{
Output("");
}
Output(String.Format("<<< SimplySerial v{0} connected via {1} >>>\n" +
"Settings : {2} baud, {3} parity, {4} data bits, {5} stop bit{6}, auto-connect {7}.\n" +
"Device : {8} {9}{10}\n{11}" +
"Settings : {2} baud, {3} parity, {4} data bits, {5} stop bit{6}, {7} encoding, auto-connect {8}\n" +
"Device : {9} {10}{11}\n{12}" +
"---\n\nUse CTRL-X to exit.\n",
version,
port.name,
@ -259,12 +278,13 @@ namespace SimplySerial
(parity == Parity.None) ? "no" : (parity.ToString()).ToLower(),
dataBits,
(stopBits == StopBits.None) ? "0" : (stopBits == StopBits.One) ? "1" : (stopBits == StopBits.OnePointFive) ? "1.5" : "2", (stopBits == StopBits.One) ? "" : "s",
(encoding.ToString() == "System.Text.UTF8Encoding") ? "UTF-8" : (convertToPrintable) ? "RAW" : "ASCII",
(autoConnect == AutoConnect.ONE) ? "on" : (autoConnect == AutoConnect.ANY) ? "any" : "off",
port.board.make,
port.board.model,
(port.isCircuitPython) ? " (CircuitPython-capable)" : "",
(logging == true) ? ($"Logfile : {logFile} (Mode = " + ((logMode == FileMode.Create) ? "OVERWRITE" : "APPEND") + ")\n" ) : ""
), flush: true);
(logging == true) ? ($"Logfile : {logFile} (Mode = " + ((logMode == FileMode.Create) ? "OVERWRITE" : "APPEND") + ")\n") : ""
), flush: true); ;
lastFlush = DateTime.Now;
DateTime start = DateTime.Now;
@ -304,6 +324,13 @@ namespace SimplySerial
// if anything was received, process it
if (received.Length > 0)
{
// if we're trying to filter out title/status updates in received data, try to ensure we've got the whole string
if (noStatus && received.Contains("\x1b"))
{
Thread.Sleep(100);
received += serialPort.ReadExisting();
}
if (forceNewline)
received = received.Replace("\r", "\n");
@ -336,7 +363,10 @@ namespace SimplySerial
if (autoConnect == AutoConnect.NONE)
ExitProgram((e.GetType() + " occurred while attempting to read/write to/from " + port.name + "."), exitCode: -1);
else
{
Console.Title = $"{port.name}: (disconnected)";
Output("\n<<< Communications Interrupted >>>\n");
}
try
{
serialPort.Dispose();
@ -348,11 +378,13 @@ namespace SimplySerial
Thread.Sleep(2000); // sort-of arbitrary delay - should be long enough to read the "interrupted" message
if (autoConnect == AutoConnect.ANY)
{
Console.Title = "SimplySerial: Searching...";
port.name = String.Empty;
Output("<<< Attemping to connect to any available COM port. Use CTRL-X to cancel >>>");
}
else if (autoConnect == AutoConnect.ONE)
{
Console.Title = $"{port.name}: Searching...";
Output("<<< Attempting to re-connect to " + port.name + ". Use CTRL-X to cancel >>>");
}
break;
@ -383,7 +415,7 @@ namespace SimplySerial
foreach (string arg in args)
{
// split argument into components based on 'key:value' formatting
string[] argument = arg.Split(new [] { ':' }, 2);
string[] argument = arg.Split(new[] { ':' }, 2);
argument[0] = argument[0].ToLower();
// help
@ -442,6 +474,18 @@ namespace SimplySerial
forceNewline = true;
}
// disable screen clearing
else if (argument[0].StartsWith("noc"))
{
clearScreen = false;
}
// disable status/title updates from virtual terminal sequences
else if (argument[0].StartsWith("nos"))
{
noStatus = true;
}
// the remainder of possible command-line arguments require two parameters, so let's enforce that now
else if (argument.Count() < 2)
{
@ -545,6 +589,30 @@ namespace SimplySerial
logFile = argument[1];
}
// specify encoding
else if (argument[0].StartsWith("e"))
{
argument[1] = argument[1].ToLower();
if (argument[1].StartsWith("a"))
{
encoding = Encoding.ASCII;
convertToPrintable = false;
}
else if (argument[1].StartsWith("r"))
{
encoding = Encoding.GetEncoding(1252);
convertToPrintable = true;
}
else if (argument[1].StartsWith("u"))
{
encoding = Encoding.UTF8;
convertToPrintable = false;
}
else
ExitProgram(("Invalid encoding specified <" + argument[1] + ">"), exitCode: -1);
}
// an invalid/incomplete argument was passed
else
{
@ -552,20 +620,34 @@ namespace SimplySerial
}
}
Console.Clear();
if (clearScreen)
{
Console.Clear();
}
if (autoConnect == AutoConnect.ANY)
{
Console.Title = "SimplySerial: Searching...";
Output("<<< Attemping to connect to any available COM port. Use CTRL-X to cancel >>>");
}
else if (autoConnect == AutoConnect.ONE)
{
Console.Clear();
if (clearScreen)
{
Console.Clear();
}
if (port.name == String.Empty)
{
Console.Title = "SimplySerial: Searching...";
Output("<<< Attempting to connect to first available COM port. Use CTRL-X to cancel >>>");
}
else
{
Console.Title = $"{port.name}: Searching...";
Output("<<< Attempting to connect to " + port.name + ". Use CTRL-X to cancel >>>");
}
}
// if we made it this far, everything has been processed and we're ready to proceed!
}
@ -574,7 +656,7 @@ namespace SimplySerial
/// Writes messages using Console.WriteLine() as long as the 'Quiet' option hasn't been enabled
/// </summary>
/// <param name="message">Message to output (assuming 'Quiet' is false)</param>
static void Output(string message, bool force=false, bool newline=true, bool flush=false)
static void Output(string message, bool force = false, bool newline = true, bool flush = false)
{
if (!SimplySerial.Quiet || force)
{
@ -582,7 +664,27 @@ namespace SimplySerial
message += "\n";
if (message.Length > 0)
{
if (noStatus)
{
Regex r = new Regex(@"\x1b\][02];.*\x1b\\");
message = r.Replace(message, string.Empty);
}
if (convertToPrintable)
{
string newMessage = "";
foreach (byte c in message)
{
if ((c > 31 && c < 128) || (c == 8) || (c == 9) || (c == 10) || (c == 13))
newMessage += (char)c;
else
newMessage += $"[{c:X2}]";
}
message = newMessage;
}
Console.Write(message);
}
if (logging)
{
@ -592,7 +694,7 @@ namespace SimplySerial
try
{
FileStream stream = new FileStream(logFile, FileMode.Append, FileAccess.Write);
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
using (StreamWriter writer = new StreamWriter(stream, encoding))
{
writer.Write(logData);
}
@ -637,6 +739,9 @@ namespace SimplySerial
Console.WriteLine(" -logmode:MODE APPEND | OVERWRITE, default is OVERWRITE");
Console.WriteLine(" -quiet don't print any application messages/errors to console");
Console.WriteLine(" -forcenewline Force linefeeds (newline) in place of carriage returns in received data.");
Console.WriteLine(" -encoding:ENC UTF8 | ASCII | RAW");
Console.WriteLine(" -noclear Don't clear the terminal screen on connection.");
Console.WriteLine(" -nostatus Block status/title updates from virtual terminal sequences.");
Console.WriteLine("\nPress CTRL-X to exit a running instance of SimplySerial.\n");
}
@ -668,7 +773,7 @@ namespace SimplySerial
/// <param name="message">Message to display - should indicate the reason why the program is terminating.</param>
/// <param name="exitCode">Code to return to parent process. Should be &lt;0 if an error occurred, &gt;=0 if program is terminating normally.</param>
/// <param name="silent">Exits without displaying a message or asking for a key press when set to 'true'</param>
static void ExitProgram(string message="", int exitCode=0, bool silent=false)
static void ExitProgram(string message = "", int exitCode = 0, bool silent = false)
{
// the serial port should be closed before exiting
if (serialPort != null && serialPort.IsOpen)
@ -708,7 +813,7 @@ namespace SimplySerial
string[] cpb_descriptions = new string[] { "CircuitPython CDC ", "Sol CDC ", "StringCarM0Ex CDC " };
List<ComPort> detectedPorts = new List<ComPort>();
foreach (var p in new ManagementObjectSearcher("root\\CIMV2", query).Get().OfType<ManagementObject>())
{
ComPort c = new ComPort();
@ -721,7 +826,7 @@ namespace SimplySerial
c.name = mName.Value;
c.num = int.Parse(c.name.Substring(3));
}
// if the port name or number cannot be determined, skip this port and move on
if (c.num < 1)
continue;
@ -741,7 +846,7 @@ namespace SimplySerial
// extract the device's friendly description (caption)
c.description = p.GetPropertyValue("Caption").ToString();
// attempt to match this device with a known board
c.board = MatchBoard(c.vid, c.pid);
@ -767,7 +872,7 @@ namespace SimplySerial
}
// add this port to our list of detected ports
detectedPorts.Add(c);
detectedPorts.Add(c);
}
return detectedPorts;
@ -788,7 +893,7 @@ namespace SimplySerial
if (mBoard == null)
{
mBoard = new Board(vid:vid, pid:pid);
mBoard = new Board(vid: vid, pid: pid);
Vendor mVendor = null;
if (boardData.vendors != null)
@ -799,7 +904,7 @@ namespace SimplySerial
return mBoard;
}
static void LoadBoards()
{
try
@ -818,7 +923,7 @@ namespace SimplySerial
}
}
/// <summary>
/// Custom string array sorting logic for SimplySerial command-line arguments
/// </summary>
@ -837,15 +942,15 @@ namespace SimplySerial
// 'l' triggers the 'list available ports' output and supersedes all other command-line arguments aside from 'help' and 'version'
// 'q' enables the 'quiet' option, which needs to be enabled before something that would normally generate console output
// 'c' is the 'comport' setting, which needs to be processed before 'autoconnect'
x = x.ToLower();
if (x.StartsWith("lo"))
x = "z"; // mask out logging options so that they are not interpreted as the list option
y = y.ToLower();
if (y.StartsWith("lo"))
y = "z"; // mask out logging options so that they are not interpreted as the list option
foreach (char c in "?hvlqc")
{
if (x.ToLower()[0] == c)

View File

@ -113,6 +113,6 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>"C:\Program Files\7-Zip\7z.exe" a "$(TargetDir)\SimplySerial_standalone.zip" "$(TargetDir)\ss.exe" "$(ProjectDir)\..\LICENSE" "$(ProjectDir)\..\README.md" "$(TargetDir)\boards.json" "$(TargetDir)\ss.exe.config" "$(TargetDir)\Newtonsoft.Json.dll"</PostBuildEvent>
<PostBuildEvent>powershell Compress-Archive -Path '$(TargetDir)\ss.exe', '$(ProjectDir)\..\LICENSE', '$(ProjectDir)\..\README.md', '$(TargetDir)\boards.json', '$(TargetDir)\ss.exe.config', '$(TargetDir)\Newtonsoft.Json.dll' -DestinationPath '$(TargetDir)\SimplySerial_standalone.zip' -Force</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@ -1,5 +1,5 @@
{
"version": "2022-08-22T10:16:04.484338",
"version": "2023-02-14T13:18:35.393375",
"vendors": [
{
"vid": "04D8",
@ -67,6 +67,12 @@
}
],
"boards": [
{
"vid": "0483",
"pid": "572A",
"make": "STMicroelectronics",
"model": "NUCLEO-F446RE - CPy"
},
{
"vid": "04D8",
"pid": "E799",
@ -205,6 +211,12 @@
"make": "Targett",
"model": "Targett Module Clip w/Wrover"
},
{
"vid": "1209",
"pid": "4203",
"make": "42. Keebs",
"model": "Frood"
},
{
"vid": "1209",
"pid": "4D43",
@ -283,6 +295,12 @@
"make": "takayoshiotake",
"model": "Octave RP2040"
},
{
"vid": "1209",
"pid": "9000",
"make": "Hack Club",
"model": "Sprig"
},
{
"vid": "1209",
"pid": "A182",
@ -337,6 +355,12 @@
"make": "Betrusted",
"model": "Simmel"
},
{
"vid": "1209",
"pid": "CB74",
"make": "0xCB",
"model": "Helios"
},
{
"vid": "1209",
"pid": "D10D",
@ -355,6 +379,12 @@
"make": "StackRduino",
"model": "StackRduino M0 PRO"
},
{
"vid": "1209",
"pid": "EF00",
"make": "2231puppy",
"model": "E-Fidget"
},
{
"vid": "1209",
"pid": "F123",
@ -391,6 +421,12 @@
"make": "Pimoroni",
"model": "PicoSystem"
},
{
"vid": "16D0",
"pid": "10ED",
"make": "Mechwild",
"model": "PillBug"
},
{
"vid": "1915",
"pid": "B001",
@ -577,6 +613,12 @@
"make": "WeAct Studio",
"model": "Pico"
},
{
"vid": "239A",
"pid": "2030",
"make": "Czech maker",
"model": "Maker badge"
},
{
"vid": "239A",
"pid": "6005",
@ -1211,7 +1253,7 @@
"vid": "239A",
"pid": "80EE",
"make": "Adafruit",
"model": "Feather ESP32S2 TFT no PSRAM"
"model": "Feather ESP32-S2 Reverse TFT"
},
{
"vid": "239A",
@ -1345,6 +1387,24 @@
"make": "Adafruit",
"model": "Feather ESP32-S3 TFT"
},
{
"vid": "239A",
"pid": "8120",
"make": "Raspberry Pi",
"model": "Pico W"
},
{
"vid": "239A",
"pid": "8122",
"make": "Adafruit",
"model": "Feather RP2040 Scorpio"
},
{
"vid": "239A",
"pid": "8124",
"make": "Adafruit",
"model": "Feather ESP32-S3 Reverse TFT"
},
{
"vid": "239A",
"pid": "D1ED",
@ -1585,6 +1645,42 @@
"make": "WIZnet",
"model": "W5500-EVB-Pico"
},
{
"vid": "2E8A",
"pid": "102C",
"make": "Invector Labs",
"model": "Challenger RP2040 WiFi/BLE"
},
{
"vid": "2E8A",
"pid": "102D",
"make": "Invector Labs",
"model": "Challenger RP2040 SD/RTC"
},
{
"vid": "2E8A",
"pid": "102E",
"make": "VCC-GND Studio",
"model": "YD-RP2040"
},
{
"vid": "2E8A",
"pid": "1032",
"make": "Invector Labs",
"model": "Challenger RP2040 SubGHz"
},
{
"vid": "2E8A",
"pid": "1039",
"make": "Waveshare Electronics",
"model": "Waveshare RP2040-LCD-1.28"
},
{
"vid": "2E8A",
"pid": "1048",
"make": "nullbits",
"model": "Bit-C PRO"
},
{
"vid": "303A",
"pid": "7001",
@ -1595,7 +1691,7 @@
"vid": "303A",
"pid": "7003",
"make": "Espressif",
"model": "ESP32-S3-DevKitC-1-N8"
"model": "ESP32-S3-DevKitC-1-N32R8"
},
{
"vid": "303A",
@ -1717,6 +1813,12 @@
"make": "Lolin",
"model": "S2 Pico"
},
{
"vid": "303A",
"pid": "80C8",
"make": "BrainBoardz",
"model": "Neuron"
},
{
"vid": "303A",
"pid": "80D1",
@ -1741,6 +1843,18 @@
"make": "FutureKeys",
"model": "HexKy_S2"
},
{
"vid": "303A",
"pid": "80E0",
"make": "BananaPi",
"model": "BPI-Leaf-S3"
},
{
"vid": "303A",
"pid": "80E6",
"make": "BananaPi",
"model": "BPI-Bit-S2"
},
{
"vid": "303A",
"pid": "80E8",
@ -1801,6 +1915,18 @@
"make": "Smart Bee Designs",
"model": "Bee-Motion-S3"
},
{
"vid": "303A",
"pid": "8117",
"make": "WEMOS",
"model": "LOLIN S3 16MB Flash 8MB PSRAM"
},
{
"vid": "303A",
"pid": "812C",
"make": "BananaPi",
"model": "BPI-PicoW-S3"
},
{
"vid": "30A4",
"pid": "0002",