Skip to content

Commit 3944b22

Browse files
authored
Merge pull request #3 from docbender/2.2.x
2.2.x
2 parents 0f549bb + 8b6be1a commit 3944b22

11 files changed

Lines changed: 576 additions & 142 deletions

File tree

Changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
2.2.0 / 22.10.2025
5+
------------------
6+
7+
- Data filtering feature
8+
- History of sent data through send dialog
9+
- Added CRC8 function
10+
411
2.1.0 / 2.9.2025
512
------------------
613

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Program isn't serial port sniffer so can't monitor port that is already open by
2222
* **Display data with timestamp or with gap between messages** - Time between received data messages is displayed (in miliseconds). In addition to the printing on the screen it allows write everything (or just communication) to a specified file.
2323
* **Log communication into the file**
2424
* **Pause data receive** - In GUI mode printing of received data can be temporarily paused for peaceful data analysis.
25+
* **Filter** - In GUI mode displayed data can be filtered.
2526
* **Send files** - Not only manually entered data can be sent, but also a prepared data file.
2627
* **Manually control RTS and DTR pins** - In GUI mode it is possible to see the pins status and also control output pins.
2728
* **Emulate serial device** - Program allows response to sender for specific message. This could be used for simple simulation of some device.
@@ -40,6 +41,7 @@ Inside message functions could be used. The function is represented by '@' follo
4041

4142
| Name | Description | Example |
4243
|-------|-------------|---------|
44+
| Crc8 | Compute CRC8 from all bytes in a packet | 0x00 0xAA @crc8 |
4345
| Crc16 | Compute CRC16 from all bytes in a packet | 0x00 0xAA @crc16 |
4446
| Rand | Generate random byte between 0-255. Value range can be specified. | 0x00 0xAA @rand[1..100] |
4547
| Sum | Compute checksum from bytes in a packet. The first and the last packet byte can be specified. | 0x03 0x00 0xAA @sum[1..] |

SerialMonitor/Config.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace SerialMonitor
1616
class Config
1717
{
1818
const string CONFIG_FILE = "serialmonitor.cfg";
19+
const string HISTORY_FILE = "serialmonitor.hist";
1920
const string START_ARGUMENTS = "StartArgs";
2021
const string START_ARGUMENTS_REGEX = "(" + START_ARGUMENTS + "=)([^\n]*)";
2122
const string HISTORY = "CommandHistory";
@@ -24,13 +25,14 @@ class Config
2425
const string FILE_LIST_REGEX = "(" + FILE_LIST + "=)([^\n]*)";
2526
public const string SETTING_PORT = "Port";
2627
public const string SETTING_BAUDRATE = "BaudRate";
27-
public const string SETTING_PARITY = "Parity";
28+
public const string SETTING_PARITY = "Parity";
2829
public const string SETTING_SHOWTIME = "ShowTime";
2930
public const string SETTING_SHOWTIMEGAP = "ShowTimeGap";
3031
public const string SETTING_SHOWSENTDATA = "ShowSentData";
31-
public const string SETTING_SHOWASCII = "ShowAscii";
32+
public const string SETTING_SHOWASCII = "ShowAscii";
3233

33-
static readonly string filePath = Path.Combine(Directory.GetCurrentDirectory(), CONFIG_FILE);
34+
static readonly string ConfigFilePath = Path.Combine(Directory.GetCurrentDirectory(), CONFIG_FILE);
35+
static readonly string CommandHistoryFilePath = Path.Combine(Directory.GetCurrentDirectory(), HISTORY_FILE);
3436

3537
/// <summary>
3638
/// Save started parameters
@@ -101,7 +103,7 @@ private static bool SaveConfigFile(string configuration)
101103
{
102104
try
103105
{
104-
using FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
106+
using FileStream fs = new FileStream(ConfigFilePath, FileMode.Create, FileAccess.Write);
105107
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
106108
{
107109
sw.Write(configuration);
@@ -252,11 +254,11 @@ private static string PrepareSave(string? configuration, string itemName, string
252254
{
253255
string cfg = "";
254256

255-
if (File.Exists(filePath))
257+
if (File.Exists(ConfigFilePath))
256258
{
257259
try
258260
{
259-
using FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
261+
using FileStream fs = new FileStream(ConfigFilePath, FileMode.Open, FileAccess.Read);
260262
if (fs.Length > 0)
261263
{
262264
using TextReader sr = new StreamReader(fs, Encoding.UTF8);
@@ -276,5 +278,36 @@ private static string PrepareSave(string? configuration, string itemName, string
276278

277279
return cfg;
278280
}
281+
282+
public static string[] ReadCommandHistory()
283+
{
284+
if (File.Exists(CommandHistoryFilePath))
285+
{
286+
try
287+
{
288+
return File.ReadAllLines(CommandHistoryFilePath);
289+
}
290+
catch (FileNotFoundException)
291+
{
292+
}
293+
catch (Exception ex)
294+
{
295+
Console.WriteLine($"Error while open the history file. {ex}");
296+
}
297+
}
298+
return [];
299+
}
300+
301+
public static void WriteCommandHistory(string[] lines)
302+
{
303+
try
304+
{
305+
File.WriteAllLines(CommandHistoryFilePath, lines);
306+
}
307+
catch (Exception ex)
308+
{
309+
Console.WriteLine($"Error write into the history file. {ex}");
310+
}
311+
}
279312
}
280313
}

SerialMonitor/Functions/BuiltInFunctions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace SerialMonitor.Functions
1414
{
1515
internal class BuiltInFunctions
1616
{
17-
public static readonly string[] Available = [nameof(Crc16), nameof(Sum), nameof(Rand)];
17+
public static readonly string[] Available = [nameof(Crc8), nameof(Crc16), nameof(Sum), nameof(Rand)];
1818
private static readonly Regex functionRegex = new Regex(@"^(\w+)(\[(\d*)\.{2}(\d*)\])?$", RegexOptions.Compiled);
1919

2020
public static bool IsAvailable(string functionName)
@@ -40,7 +40,9 @@ public static IFunction Get(string functionName, int position)
4040
int start = match.Groups[2].Success && match.Groups[3].Success && match.Groups[3].Value.Length > 0 ? int.Parse(match.Groups[3].Value) : 0;
4141
int end = match.Groups[2].Success && match.Groups[4].Success && match.Groups[4].Value.Length > 0 ? int.Parse(match.Groups[4].Value) : int.MaxValue;
4242

43-
if (f.Equals("Crc16"))
43+
if (f.Equals("Crc8"))
44+
return new Crc8(position, start, end);
45+
else if (f.Equals("Crc16"))
4446
return new Crc16(position, start, end);
4547
else if (f.Equals("Sum"))
4648
return new Sum(position, start, end);

SerialMonitor/Functions/Crc8.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//---------------------------------------------------------------------------
2+
//
3+
// Name: Crc8.cs
4+
// Author: Vita Tucek
5+
// Created: 18.10.2025
6+
// License: MIT
7+
// Description: CRC8 calculation
8+
//
9+
//---------------------------------------------------------------------------
10+
11+
namespace SerialMonitor.Functions
12+
{
13+
public class Crc8 : FunctionBase
14+
{
15+
public Crc8(int position) : base(position)
16+
{
17+
}
18+
19+
public Crc8(int position, int start, int end) : base(position, start, end)
20+
{
21+
}
22+
23+
public override int Size => 1;
24+
25+
/// <summary>
26+
/// Compute over specified length
27+
/// </summary>
28+
/// <param name="data"></param>
29+
/// <param name="length"></param>
30+
/// <returns></returns>
31+
public static byte ComputeCrc(byte[] data, int position, int start, int end)
32+
{
33+
int dataend = end < position ? end : position - 1;
34+
int crc = 0;
35+
int i, j;
36+
37+
for (j = start; j <= dataend; j++)
38+
{
39+
crc ^= (data[j] << 8);
40+
41+
for (i = 0; i < 8; i++)
42+
{
43+
if ((crc & 0x8000) != 0)
44+
crc ^= (0x1070 << 3);
45+
46+
crc <<= 1;
47+
}
48+
}
49+
return (byte)(crc >> 8);
50+
}
51+
52+
public override void Compute(byte[] data)
53+
{
54+
var crc = Crc8.ComputeCrc(data, Position, Start, End);
55+
data[Position] = crc;
56+
}
57+
58+
/// <summary>
59+
/// Verify data with CRC included
60+
/// </summary>
61+
/// <param name="data"></param>
62+
/// <param name="length"></param>
63+
/// <returns></returns>
64+
public static bool Verify(byte[] data)
65+
{
66+
return Verify(data, data.Length);
67+
}
68+
69+
/// <summary>
70+
/// Verify data with CRC included
71+
/// </summary>
72+
/// <param name="data"></param>
73+
/// <param name="length"></param>
74+
/// <returns></returns>
75+
public static bool Verify(byte[] data, int length)
76+
{
77+
if (length < 3)
78+
return false;
79+
byte computed = ComputeCrc(data, length - 1, 0, length - 1);
80+
byte received = data[length - 1];
81+
82+
return computed == received;
83+
}
84+
}
85+
}

SerialMonitor/LogRecord.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.CodeDom;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using static System.Runtime.InteropServices.JavaScript.JSType;
9+
10+
namespace SerialMonitor
11+
{
12+
public enum LogRecordType
13+
{
14+
DataReceived,
15+
DataSent,
16+
ControlPinChanged,
17+
ControlPinOn,
18+
ControlPinOff,
19+
Time,
20+
Error,
21+
Warning,
22+
Default,
23+
}
24+
25+
internal class LogRecord
26+
{
27+
public static bool ShowTime { get; set; } = true;
28+
public LogRecord(string text, LogRecordType type, TraceEventType level)
29+
{
30+
Text = text;
31+
Level = level;
32+
Type = type;
33+
TimeStamp = DateTime.Now;
34+
}
35+
public string Text { get; set; }
36+
public TraceEventType Level { get; }
37+
public LogRecordType Type { get; }
38+
public DateTime TimeStamp { get; private set; }
39+
public int Length { get => Text.Length; }
40+
41+
public static LogRecord operator +(LogRecord left, LogRecord right) => (new LogRecord(left.Text + right.Text, left.Type, left.Level));
42+
public static LogRecord operator +(LogRecord left, string right) => (new LogRecord(left.Text + right, left.Type, left.Level));
43+
public static LogRecord operator +(LogRecord operand) => operand;
44+
45+
public void Append(string message)
46+
{
47+
Text += message;
48+
}
49+
50+
public override string ToString()
51+
{
52+
return Render();
53+
}
54+
55+
private string Render()
56+
{
57+
if (ShowTime && (Type == LogRecordType.DataSent || Type == LogRecordType.DataReceived))
58+
return $"{TimeStamp:HH:mm:ss.fff} {Text}";
59+
60+
return Text;
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)