OSDP.Net 5.2.1
A .NET library for implementing the Open Supervised Device Protocol (OSDP)
Loading...
Searching...
No Matches
SerialPortOsdpConnection.cs
1using System;
2using System.Collections.Generic;
3using System.IO.Ports;
4using System.Linq;
5using System.Threading;
6using System.Threading.Tasks;
7
9{
12 {
13 private static readonly TimeSpan OpenRetryTimeout = TimeSpan.FromSeconds(1);
14 private static readonly TimeSpan OpenRetryInterval = TimeSpan.FromMilliseconds(25);
15
16 private readonly string _portName;
17 private SerialPort _serialPort;
18
27 public static readonly int[] StandardBaudRates = [9600, 19200, 38400, 57600, 115200, 230400, 460800];
28
33 public SerialPortOsdpConnection(string portName, int baudRate) : base(baudRate)
34 {
35 _portName = portName ?? throw new ArgumentNullException(nameof(portName));
36 }
37
51 public static IEnumerable<SerialPortOsdpConnection> EnumBaudRates(string portName, int[] rates = null)
52 {
53 return (rates ?? StandardBaudRates).Select(rate => new SerialPortOsdpConnection(portName, rate));
54 }
55
66 public bool DiscardBuffersBeforeWrite { get; set; } = true;
67
76 public override async Task Open()
77 {
78 if (_serialPort != null) return;
79
80 var deadline = DateTime.UtcNow + OpenRetryTimeout;
81 while (true)
82 {
83 var serialPort = new SerialPort(_portName, BaudRate);
84 try
85 {
86 serialPort.Open();
87 _serialPort = serialPort;
88 IsOpen = true;
89 return;
90 }
91 catch (UnauthorizedAccessException) when (DateTime.UtcNow < deadline)
92 {
93 serialPort.Dispose();
94 }
95 catch
96 {
97 serialPort.Dispose();
98 throw;
99 }
100
101 await Task.Delay(OpenRetryInterval).ConfigureAwait(false);
102 }
103 }
104
117 public void SetBaudRate(int baudRate)
118 {
119 if (baudRate <= 0)
120 {
121 throw new ArgumentOutOfRangeException(nameof(baudRate), "Baud rate must be greater than zero.");
122 }
123
124 BaudRate = baudRate;
125
126 var serialPort = _serialPort;
127 if (serialPort != null && serialPort.IsOpen)
128 {
129 serialPort.BaudRate = baudRate;
130 }
131 }
132
151 public async Task WaitForTransmitCompleteAsync(int frameByteCount, CancellationToken token = default)
152 {
153 var serialPort = _serialPort;
154 if (serialPort == null || !serialPort.IsOpen) return;
155
156 while (!token.IsCancellationRequested && serialPort.BytesToWrite > 0)
157 {
158 await Task.Delay(1, token).ConfigureAwait(false);
159 }
160
161 if (frameByteCount <= 0) return;
162
163 var wireTime = TimeSpan.FromSeconds(frameByteCount * 10.0 / BaudRate);
164 await Task.Delay(wireTime, token).ConfigureAwait(false);
165 }
166
168 public override Task Close()
169 {
170 _serialPort?.Close();
171 _serialPort?.Dispose();
172 _serialPort = null;
173 IsOpen = false;
174 return Task.CompletedTask;
175 }
176
178 public override async Task WriteAsync(byte[] buffer)
179 {
181 {
182 // Found an issue where many timeouts would fill up the receive buffer.
183 // When writing to the port, there should be nothing in the buffers.
184 _serialPort.DiscardInBuffer();
185 _serialPort.DiscardOutBuffer();
186 }
187
188 await _serialPort.BaseStream.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
189 }
190
192 public override async Task<int> ReadAsync(byte[] buffer, CancellationToken token)
193 {
194 var task = _serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length, token);
195
196 if (await Task.WhenAny(task, Task.Delay(-1, token)) == task)
197 {
198 return await task.ConfigureAwait(false);
199 }
200
201 throw new TimeoutException();
202 }
203
205 public override string ToString()
206 {
207 return _portName;
208 }
209 }
210}
int BaudRate
Speed of the connection.
OsdpConnection(int baudRate)
Creates an instance of OsdpConnection.
virtual bool IsOpen
Is the connection open and ready to communicate.
SerialPortOsdpConnection(string portName, int baudRate)
Initializes a new instance of the T:OSDP.Net.Connections.SerialPortOsdpConnection class.
static IEnumerable< SerialPortOsdpConnection > EnumBaudRates(string portName, int[] rates=null)
A helper method that returns a lazily instantiated set of SerialPortOsdpConnection instances,...
bool DiscardBuffersBeforeWrite
Gets or sets a value indicating whether the receive and transmit buffers are discarded before every w...
override async Task< int > ReadAsync(byte[] buffer, CancellationToken token)
Read from connection.Number of actual bytes read
override Task Close()
Close the connection for communications.
override async Task Open()
Open the connection for communications.
void SetBaudRate(int baudRate)
Changes the baud rate of the connection, retuning the port in place if it is open.
static readonly int[] StandardBaudRates
Baud rates to try when searching for a device: 9600, 19200, 38400, 57600, 115200, 230400,...
async Task WaitForTransmitCompleteAsync(int frameByteCount, CancellationToken token=default)
Waits until buffered output has been handed to the hardware and had time to clear it.
override async Task WriteAsync(byte[] buffer)
Write to connection.
A connection whose line rate can be changed while it stays open.