Skip to content

Commit fcfcf44

Browse files
committed
23 - Refactored serial reading
- made SerialMonitor disposable - introduced -w command arg flag - creating optional telegramexporter for storing telegrams
1 parent 417378f commit fcfcf44

File tree

5 files changed

+117
-74
lines changed

5 files changed

+117
-74
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,8 @@ $RECYCLE.BIN/
452452
!.vscode/tasks.json
453453
!.vscode/launch.json
454454
!.vscode/extensions.json
455+
456+
457+
# My own files to ignore
458+
*.ssm
459+
*.bin

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"preLaunchTask": "build",
99
// If you have changed target frameworks, make sure to update the program path.
1010
"program": "${workspaceFolder}/RS485 Monitor/bin/Debug/net8.0/RS485 Monitor.dll",
11-
"args": [""],
11+
"args": ["-w"],
1212
"cwd": "${workspaceFolder}",
1313
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
1414
"console": "internalConsole",

RS485 Monitor/src/CmdOptions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
public class CmdOptions
77
{
88
[Value(0, MetaName = "InputFile", HelpText = "File to parse")]
9-
public String? InputFile { get; set; }
9+
public string? InputFile { get; set; }
1010

1111
[Option('r', "replay", HelpText = "Replay data on serial port", Default = false)]
12-
public bool replayOnSerial { get; set; }
12+
public bool ReplayOnSerial { get; set; }
1313

1414
[Option('g', "group", HelpText = "Group telegrams in output", Default = false)]
15-
public bool groupOutput { get; set; }
16-
}
15+
public bool GroupOutput { get; set; }
16+
17+
[Option('w', "write-to-file", HelpText = "Write telegrams including timestamp to a file", Default = false)]
18+
public bool WriteToFile { get; set; }
19+
}

RS485 Monitor/src/Program.cs

Lines changed: 91 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
using NLog.Extensions.Logging;
33
using Microsoft.Extensions.Configuration;
44
using CommandLine;
5+
using RS485_Monitor.Utils.Storage;
6+
using System.Runtime.CompilerServices;
7+
8+
const string FILE_EXTENSION = ".ssm";
59

610
// Configuration
711
var config = new ConfigurationBuilder()
@@ -10,25 +14,26 @@
1014

1115
var sec = config.GetSection("NLog");
1216
LogManager.Configuration = new NLogLoggingConfiguration(sec);
13-
NLog.Logger log = LogManager.GetCurrentClassLogger();
17+
Logger log = LogManager.GetCurrentClassLogger();
1418

1519
Configuration cfg = new(config.GetSection("Monitor"));
1620

17-
// Commandline parser
18-
String? parseFile = null;
21+
// command line parser
22+
string? parseFile = null;
1923
bool replayToSerial = false;
2024
bool groupOutput = false;
21-
25+
bool writeToFile = false;
2226

2327
var result = Parser.Default.ParseArguments<CmdOptions>(args)
24-
.WithParsed<CmdOptions>(o =>
28+
.WithParsed(o =>
2529
{
2630
if (o.InputFile != null)
2731
{
2832
parseFile = o.InputFile;
2933
}
30-
replayToSerial = o.replayOnSerial;
31-
groupOutput = o.groupOutput;
34+
replayToSerial = o.ReplayOnSerial;
35+
groupOutput = o.GroupOutput;
36+
writeToFile = o.WriteToFile;
3237
}
3338
);
3439

@@ -40,15 +45,7 @@
4045
}
4146

4247
// Configure output
43-
IUserVisualizable printer;
44-
if (groupOutput)
45-
{
46-
printer = new ConsolePrinter();
47-
}
48-
else
49-
{
50-
printer = new LogPrinter();
51-
}
48+
IUserVisualizable printer = groupOutput ? new ConsolePrinter() : new LogPrinter();
5249

5350
// Select execution
5451
if (parseFile != null)
@@ -63,6 +60,83 @@
6360
StartMonitor(cfg);
6461
}
6562

63+
/// <summary>
64+
/// Start the serial monitor
65+
/// </summary>
66+
void StartMonitor(Configuration cfg)
67+
{
68+
// Semaphore for ending the monitor
69+
Semaphore endMonitor = new(0, 1);
70+
71+
// Register CTRL+C
72+
Console.CancelKeyPress += new ConsoleCancelEventHandler((sender, args) =>
73+
{
74+
log.Info("Exiting ...");
75+
76+
// Set cancel to true to prevent default CTRL+C behaviour
77+
args.Cancel = true;
78+
79+
// release semaphore
80+
endMonitor.Release();
81+
});
82+
83+
log.Info($"Starting Serial Monitor on port {cfg.ComPort}");
84+
85+
// create telegram exporter
86+
TelegramExporter? exporter = null;
87+
if (writeToFile)
88+
{
89+
FileInfo? outputFile = null;
90+
string filename = DateTime.Now.ToString("yyyyMMdd_HHmmss") + "_telegram" + FILE_EXTENSION;
91+
92+
// Determine full output file path
93+
if (cfg.OutputDir != null)
94+
{
95+
outputFile = new(cfg.OutputDir + "/" + filename);
96+
}
97+
else
98+
{
99+
outputFile = new(filename);
100+
}
101+
102+
// create exporter
103+
exporter = new(outputFile.OpenWrite());
104+
}
105+
106+
// Start serial monitor on the given port
107+
using (SerialMonitor monitor = new(cfg.ComPort, cfg.WriteRawData))
108+
{
109+
if (cfg.OutputDir != null)
110+
{
111+
monitor.OutputDir = cfg.OutputDir;
112+
}
113+
monitor.TelegramReceived += (o, e) =>
114+
{
115+
// Print the received telegram
116+
printer.PrintTelegram(e.Telegram);
117+
exporter?.PushTelegram(e.Telegram);
118+
};
119+
120+
// Start reading monitor
121+
try
122+
{
123+
monitor.Start();
124+
}
125+
catch (IOException ex)
126+
{
127+
log.Fatal(ex, "Could not start monitor");
128+
return;
129+
}
130+
131+
// Wait for CTRL+C
132+
endMonitor.WaitOne();
133+
}
134+
log.Info("Monitor stopped");
135+
136+
// close exporter
137+
exporter?.Dispose();
138+
}
139+
66140

67141
/// <summary>
68142
/// Read a local file and parse it
@@ -72,7 +146,7 @@ async Task ReadLocalFile(String file)
72146
TelegramParser parser = new();
73147
TelegramPlayer player = new(cfg.ReplayCycle);
74148

75-
// Register new telegram handler
149+
// Register new telegram handler
76150
parser.NewTelegram += (sender, evt) =>
77151
{
78152
BaseTelegram telegram = ((TelegramParser.TelegramArgs)evt).Telegram;
@@ -105,49 +179,6 @@ async Task ReadLocalFile(String file)
105179
}
106180

107181

108-
/// <summary>
109-
/// Start the serial monitor
110-
/// </summary>
111-
void StartMonitor(Configuration cfg)
112-
{
113-
log.Info($"Starting Serial Monitor on port {cfg.ComPort}");
114-
115-
SerialMonitor monitor = new(cfg.ComPort, cfg.WriteRawData);
116-
if (cfg.OutputDir != null)
117-
{
118-
monitor.OutputDir = cfg.OutputDir;
119-
}
120-
monitor.TelegramReceived += (o, e) =>
121-
{
122-
// Print the received telegram
123-
printer.PrintTelegram(e.Telegram);
124-
};
125-
126-
// Register CTRL+C
127-
Console.CancelKeyPress += delegate
128-
{
129-
log.Info("Exiting ...");
130-
monitor.Stop();
131-
};
132-
133-
// Start reading monitor
134-
try
135-
{
136-
monitor.Start();
137-
}
138-
catch (System.IO.IOException ex)
139-
{
140-
log.Fatal(ex, "Could not start monitor");
141-
return;
142-
}
143-
144-
// Endless loop
145-
while (monitor.Running)
146-
{
147-
Thread.Sleep(10);
148-
}
149-
}
150-
151182

152183
/// <summary>
153184
/// Read a local file and parse it

RS485 Monitor/src/SerialMonitor.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
using System.IO.Ports;
44
using NLog;
5-
using System.Diagnostics;
6-
using System.Text;
75

86
/// <summary>
97
/// Class reading data from the serial interface and parsing using the TelegramParser.
108
/// </summary>
11-
public class SerialMonitor
9+
public class SerialMonitor : IDisposable
1210
{
1311
#region Private Members
1412
/// <summary>
@@ -56,7 +54,7 @@ public class SerialMonitor
5654
/// </summary>
5755
private const int BAUDRATE = 9600;
5856
/// <summary>
59-
/// Maximum size of the buffer / chunks
57+
/// Maximum size of the buffer / chunks
6058
/// </summary>
6159
private const int BUFFER_SIZE = 256;
6260
#endregion
@@ -85,11 +83,12 @@ public SerialMonitor(string comPort, bool writeRawData = false)
8583
parser = new();
8684
parser.NewTelegram += (o, t) =>
8785
{
88-
BaseTelegram? tel = (t as TelegramParser.TelegramArgs)?.Telegram;
86+
var args = t as TelegramParser.TelegramArgs;
8987

90-
if (tel != null && TelegramReceived != null)
88+
if (args !=null)
9189
{
92-
TelegramReceived.Invoke(this, new TelegramParser.TelegramArgs(tel));
90+
// Forward the telegram
91+
TelegramReceived?.Invoke(this, args);
9392
}
9493
};
9594
}
@@ -111,7 +110,7 @@ private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs args
111110
}
112111
buffer = new byte[bytesToRead];
113112

114-
// Read data
113+
// Read data
115114
int readBytes = port.Read(buffer, 0, bytesToRead);
116115

117116
if (readBytes != bytesToRead)
@@ -163,4 +162,9 @@ public void Stop()
163162

164163
Running = false;
165164
}
166-
}
165+
166+
public void Dispose()
167+
{
168+
Stop();
169+
}
170+
}

0 commit comments

Comments
 (0)