HamBook – Blame information for rev 28
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
3 | office | 1 | using HamBook.Radios.Generic; |
2 | using HamBook.Radios; |
||
3 | using System; |
||
4 | using System.Collections.Generic; |
||
5 | using System.IO.Ports; |
||
6 | using System.Linq; |
||
7 | using System.Text; |
||
8 | using System.Threading; |
||
9 | using System.Threading.Tasks; |
||
10 | using Serilog; |
||
11 | using HamBook.Properties; |
||
12 | using Serilog.Events; |
||
7 | office | 13 | using System.Media; |
14 | using System.Reflection; |
||
9 | office | 15 | using RJCP.IO.Ports; |
16 | using System.Diagnostics; |
||
17 | using System.IO; |
||
12 | office | 18 | using Toasts; |
19 | using System.Drawing; |
||
20 | using Configuration; |
||
21 | office | 21 | using System.Security.Cryptography; |
3 | office | 22 | |
23 | namespace HamBook |
||
24 | { |
||
25 | public class BandScan |
||
26 | { |
||
27 | private CancellationTokenSource _scanningCancellationTokenSource; |
||
21 | office | 28 | private CancellationToken _scanningCancellationToken; |
3 | office | 29 | |
30 | private CatAssemblies _catAssemblies; |
||
31 | private int _minFrequency; |
||
32 | private int _maxFrequency; |
||
9 | office | 33 | private SerialPortStream _serialPort; |
12 | office | 34 | private Configuration.Configuration _configuration; |
5 | office | 35 | private int _currentFrequency; |
9 | office | 36 | private Task _scanTask; |
3 | office | 37 | |
38 | private BandScan() |
||
39 | { |
||
40 | } |
||
41 | |||
12 | office | 42 | public BandScan(CatAssemblies catAssemblies, int min, int max, SerialPortStream serialPort, Configuration.Configuration configuration) : this() |
3 | office | 43 | { |
44 | _catAssemblies = catAssemblies; |
||
45 | _minFrequency = min; |
||
46 | _maxFrequency = max; |
||
47 | _serialPort = serialPort; |
||
12 | office | 48 | _configuration = configuration; |
3 | office | 49 | |
50 | } |
||
51 | |||
23 | office | 52 | public async void Start(int stepFrequency, int pauseTime, bool autoTune = false) |
3 | office | 53 | { |
21 | office | 54 | if(_scanTask != null) |
55 | { |
||
56 | if (!_scanningCancellationToken.IsCancellationRequested) |
||
57 | { |
||
58 | _scanningCancellationTokenSource.Cancel(); |
||
59 | } |
||
60 | |||
61 | await _scanTask; |
||
62 | _scanTask = null; |
||
63 | } |
||
64 | |||
3 | office | 65 | _scanningCancellationTokenSource = new CancellationTokenSource(); |
66 | _scanningCancellationToken = _scanningCancellationTokenSource.Token; |
||
5 | office | 67 | |
23 | office | 68 | _scanTask = Scan(stepFrequency, pauseTime, autoTune); |
3 | office | 69 | } |
70 | |||
23 | office | 71 | public async void Start(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune = false) |
3 | office | 72 | { |
21 | office | 73 | if (_scanTask != null) |
3 | office | 74 | { |
21 | office | 75 | if (!_scanningCancellationToken.IsCancellationRequested) |
76 | { |
||
77 | _scanningCancellationTokenSource.Cancel(); |
||
78 | } |
||
79 | |||
80 | await _scanTask; |
||
81 | _scanTask = null; |
||
3 | office | 82 | } |
9 | office | 83 | |
21 | office | 84 | _scanningCancellationTokenSource = new CancellationTokenSource(); |
85 | _scanningCancellationToken = _scanningCancellationTokenSource.Token; |
||
86 | |||
23 | office | 87 | _scanTask = Scan(stepFrequency, pauseTime, pauseDetectTime, autoTune); |
21 | office | 88 | } |
89 | |||
90 | public async Task Stop() |
||
91 | { |
||
92 | if (_scanTask != null) |
||
9 | office | 93 | { |
21 | office | 94 | if (!_scanningCancellationToken.IsCancellationRequested) |
95 | { |
||
96 | _scanningCancellationTokenSource.Cancel(); |
||
97 | } |
||
98 | |||
9 | office | 99 | await _scanTask; |
100 | _scanTask = null; |
||
101 | } |
||
3 | office | 102 | } |
103 | |||
23 | office | 104 | private async Task Scan(int stepFrequency, int pauseTime, bool autoTune) |
3 | office | 105 | { |
9 | office | 106 | if (!_serialPort.IsOpen) |
107 | { |
||
108 | _serialPort.Open(); |
||
109 | } |
||
110 | |||
111 | _serialPort.DiscardInBuffer(); |
||
112 | |||
113 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
||
114 | |||
3 | office | 115 | try |
116 | { |
||
117 | |||
5 | office | 118 | _currentFrequency = _minFrequency; |
3 | office | 119 | |
120 | do |
||
121 | { |
||
5 | office | 122 | var taskCompletionSource = new TaskCompletionSource<bool>(); |
3 | office | 123 | |
5 | office | 124 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
21 | office | 125 | Task.Delay(TimeSpan.FromSeconds(pauseTime), _scanningCancellationToken) |
9 | office | 126 | .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None); |
5 | office | 127 | #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
3 | office | 128 | |
7 | office | 129 | using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav"))) |
130 | { |
||
131 | soundPlayer.Play(); |
||
9 | office | 132 | await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken); |
7 | office | 133 | } |
5 | office | 134 | |
23 | office | 135 | if (autoTune) |
136 | { |
||
137 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _scanningCancellationToken); |
||
138 | |||
139 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _scanningCancellationToken); |
||
140 | } |
||
141 | |||
21 | office | 142 | await taskCompletionSource.Task; |
143 | |||
144 | _currentFrequency = _currentFrequency + stepFrequency; |
||
145 | if (_currentFrequency > _maxFrequency) |
||
146 | { |
||
147 | _currentFrequency = _minFrequency; |
||
148 | } |
||
149 | if (_currentFrequency < _minFrequency) |
||
150 | { |
||
151 | _currentFrequency = _minFrequency; |
||
152 | } |
||
153 | |||
154 | } while (!_scanningCancellationToken.IsCancellationRequested); |
||
155 | } |
||
156 | catch (Exception exception) |
||
157 | { |
||
158 | Log.Error(exception, Resources.Scanning_aborted); |
||
159 | } |
||
160 | finally |
||
161 | { |
||
162 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.OFF }); |
||
163 | |||
164 | if (_serialPort.IsOpen) |
||
165 | { |
||
166 | _serialPort.Close(); |
||
167 | |||
168 | _serialPort.DiscardInBuffer(); |
||
169 | } |
||
170 | } |
||
171 | } |
||
172 | |||
23 | office | 173 | private async Task Scan(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune) |
21 | office | 174 | { |
175 | if (!_serialPort.IsOpen) |
||
176 | { |
||
177 | _serialPort.Open(); |
||
178 | } |
||
179 | |||
180 | _serialPort.DiscardInBuffer(); |
||
181 | |||
182 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
||
183 | |||
184 | try |
||
185 | { |
||
186 | |||
187 | _currentFrequency = _minFrequency; |
||
188 | |||
189 | do |
||
190 | { |
||
191 | var taskCompletionSource = new TaskCompletionSource<bool>(); |
||
192 | |||
193 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
||
194 | Task.Delay(TimeSpan.FromSeconds(pauseTime), _scanningCancellationToken) |
||
195 | .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None); |
||
196 | #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
||
197 | |||
198 | using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav"))) |
||
199 | { |
||
200 | soundPlayer.Play(); |
||
201 | await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken); |
||
202 | } |
||
203 | |||
23 | office | 204 | if(autoTune) |
205 | { |
||
28 | office | 206 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.OFF }); |
23 | office | 207 | |
28 | office | 208 | try |
209 | { |
||
210 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _scanningCancellationToken); |
||
211 | |||
212 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _scanningCancellationToken); |
||
213 | |||
214 | do |
||
215 | { |
||
216 | await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken); |
||
217 | |||
218 | try |
||
219 | { |
||
220 | if(await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { }, _scanningCancellationToken) != TunerState.TUNING_START) |
||
221 | { |
||
222 | break; |
||
223 | } |
||
224 | } |
||
225 | catch(Exception) |
||
226 | { |
||
227 | // retry |
||
228 | } |
||
229 | |||
230 | } while (!_scanningCancellationToken.IsCancellationRequested); |
||
231 | } |
||
232 | finally |
||
233 | { |
||
234 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
||
235 | } |
||
23 | office | 236 | } |
237 | |||
9 | office | 238 | using (var memoryStream = new MemoryStream()) |
239 | { |
||
240 | _serialPort.DiscardInBuffer(); |
||
5 | office | 241 | |
9 | office | 242 | await taskCompletionSource.Task; |
243 | |||
21 | office | 244 | var count = _serialPort.BaudRate / sizeof(byte) * pauseTime; |
9 | office | 245 | await _serialPort.CopyToAsync(memoryStream, count, _scanningCancellationToken); |
246 | |||
247 | memoryStream.Position = 0L; |
||
248 | |||
11 | office | 249 | // TODO: radios |
9 | office | 250 | var result = Encoding.ASCII.GetString(memoryStream.ToArray()); |
11 | office | 251 | foreach (var split in result.Split(Radios.Generic.Constants.EOT)) |
9 | office | 252 | { |
17 | office | 253 | if(string.IsNullOrEmpty(split)) |
254 | { |
||
255 | continue; |
||
256 | } |
||
257 | |||
258 | try |
||
9 | office | 259 | { |
18 | office | 260 | switch (_catAssemblies.CatParse<BusyState>("BY", new object[] { $"{split}{Radios.Generic.Constants.EOT}" })) |
17 | office | 261 | { |
262 | case BusyState.ON: |
||
21 | office | 263 | if (_configuration.Notifications.TryGetNotificationState(NotificationType.SignalScanDetect, out var notificationState)) |
17 | office | 264 | { |
21 | office | 265 | continue; |
266 | } |
||
12 | office | 267 | |
21 | office | 268 | var toastFrom = new ToastForm( |
269 | $"{Resources.Signal_detected_during_scan}", |
||
270 | $"{Resources.Frequency}: {_currentFrequency}Hz", |
||
271 | notificationState.LingerTime, |
||
272 | Constants.AssemblyIcon); |
||
12 | office | 273 | |
21 | office | 274 | toastFrom.Show(); |
275 | |||
276 | await Task.Delay(TimeSpan.FromSeconds(pauseDetectTime), _scanningCancellationToken); |
||
17 | office | 277 | continue; |
278 | } |
||
9 | office | 279 | } |
18 | office | 280 | catch (TargetInvocationException exception) when (exception.InnerException is UnmatchedRadioResponseException) |
17 | office | 281 | { |
282 | // suppress |
||
283 | } |
||
18 | office | 284 | catch (Exception exception) |
17 | office | 285 | { |
18 | office | 286 | Log.Warning(exception, Resources.Unexpected_failure_while_scanning); |
17 | office | 287 | } |
9 | office | 288 | } |
289 | } |
||
290 | |||
21 | office | 291 | _currentFrequency = _currentFrequency + stepFrequency; |
5 | office | 292 | if(_currentFrequency > _maxFrequency) |
3 | office | 293 | { |
5 | office | 294 | _currentFrequency = _minFrequency; |
3 | office | 295 | } |
5 | office | 296 | if(_currentFrequency < _minFrequency) |
3 | office | 297 | { |
5 | office | 298 | _currentFrequency = _minFrequency; |
3 | office | 299 | } |
300 | |||
5 | office | 301 | } while(!_scanningCancellationToken.IsCancellationRequested); |
3 | office | 302 | } |
303 | catch(Exception exception) |
||
304 | { |
||
305 | Log.Error(exception, Resources.Scanning_aborted); |
||
306 | } |
||
9 | office | 307 | finally |
308 | { |
||
309 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.OFF }); |
||
310 | |||
311 | if (_serialPort.IsOpen) |
||
312 | { |
||
313 | _serialPort.Close(); |
||
314 | |||
315 | _serialPort.DiscardInBuffer(); |
||
316 | } |
||
317 | } |
||
3 | office | 318 | } |
319 | } |
||
320 | } |