HamBook – Blame information for rev 54

Subversion Repositories:
Rev:
Rev Author Line No. Line
54 office 1 using System;
2 using System.IO;
3 using System.Media;
4 using System.Reflection;
3 office 5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
54 office 8 using Configuration;
3 office 9 using HamBook.Properties;
54 office 10 using HamBook.Radios;
11 using HamBook.Radios.Generic;
9 office 12 using RJCP.IO.Ports;
54 office 13 using Serilog;
12 office 14 using Toasts;
3 office 15  
16 namespace HamBook
17 {
18 public class BandScan
19 {
54 office 20 private readonly CatAssemblies _catAssemblies;
21 private readonly Configuration.Configuration _configuration;
22 private readonly int _maxFrequency;
23 private readonly int _minFrequency;
24 private readonly SerialPortStream _serialPort;
25 private int _currentFrequency;
26 private CancellationToken _scanningCancellationToken;
3 office 27 private CancellationTokenSource _scanningCancellationTokenSource;
36 office 28 private Thread _scanThread;
3 office 29  
54 office 30 private BandScan()
3 office 31 {
32 }
33  
54 office 34 public BandScan(CatAssemblies catAssemblies, int min, int max, SerialPortStream serialPort,
35 Configuration.Configuration configuration) : this()
3 office 36 {
37 _catAssemblies = catAssemblies;
38 _minFrequency = min;
39 _maxFrequency = max;
40 _serialPort = serialPort;
12 office 41 _configuration = configuration;
3 office 42 }
43  
36 office 44 public void Start(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune = false)
3 office 45 {
36 office 46 if (_scanThread != null)
21 office 47 {
54 office 48 if (!_scanningCancellationToken.IsCancellationRequested) _scanningCancellationTokenSource.Cancel();
21 office 49  
36 office 50 _scanThread.Join();
51 _scanThread = null;
21 office 52 }
53  
3 office 54 _scanningCancellationTokenSource = new CancellationTokenSource();
55 _scanningCancellationToken = _scanningCancellationTokenSource.Token;
5 office 56  
54 office 57 _scanThread = new Thread(Scan);
36 office 58 _scanThread.Start(new BandScanParameters(stepFrequency, pauseTime, pauseDetectTime, autoTune));
3 office 59 }
60  
39 office 61 public void Stop()
3 office 62 {
36 office 63 if (_scanThread != null)
3 office 64 {
54 office 65 if (!_scanningCancellationToken.IsCancellationRequested) _scanningCancellationTokenSource.Cancel();
21 office 66  
36 office 67 _scanThread.Join();
68 _scanThread = null;
3 office 69 }
21 office 70 }
71  
36 office 72 private async void Scan(object obj)
21 office 73 {
36 office 74 var bandScanParameters = (BandScanParameters)obj;
21 office 75  
54 office 76 if (!_serialPort.IsOpen) _serialPort.Open();
9 office 77  
78 _serialPort.DiscardInBuffer();
79  
3 office 80 try
81 {
5 office 82 _currentFrequency = _minFrequency;
3 office 83  
84 do
85 {
5 office 86 var taskCompletionSource = new TaskCompletionSource<bool>();
3 office 87  
54 office 88 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
89 .GetManifestResourceStream("HamBook.Effects.pot.wav")))
7 office 90 {
91 soundPlayer.Play();
39 office 92  
54 office 93 await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency },
94 _scanningCancellationToken);
7 office 95 }
5 office 96  
36 office 97 if (bandScanParameters.AutoTune)
23 office 98 {
54 office 99 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON },
100 _scanningCancellationToken);
23 office 101  
39 office 102 do
103 {
104 await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken);
105  
106 try
107 {
54 office 108 var tuneState = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { },
109 _scanningCancellationToken);
39 office 110  
54 office 111 if (tuneState != TunerState.TUNER_ON) break;
39 office 112 }
113 catch (Exception)
114 {
115 // retry
116 }
117 } while (!_scanningCancellationToken.IsCancellationRequested);
118  
54 office 119 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START },
120 _scanningCancellationToken);
23 office 121  
36 office 122 do
123 {
124 await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken);
21 office 125  
36 office 126 try
127 {
54 office 128 var tuneState = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { },
129 _scanningCancellationToken);
39 office 130  
54 office 131 if (tuneState != TunerState.TUNING_START) break;
36 office 132 }
133 catch (Exception)
134 {
135 // retry
136 }
137 } while (!_scanningCancellationToken.IsCancellationRequested);
21 office 138 }
139  
36 office 140 _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON });
21 office 141  
36 office 142 try
143 {
144 using (var memoryStream = new MemoryStream())
145 {
21 office 146 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
36 office 147 Task.Delay(TimeSpan.FromSeconds(bandScanParameters.PauseTime), _scanningCancellationToken)
148 .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None);
21 office 149 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
150  
36 office 151 await taskCompletionSource.Task;
21 office 152  
54 office 153 await _serialPort.CopyToAsync(memoryStream, _serialPort.BytesToRead,
154 _scanningCancellationToken);
23 office 155  
36 office 156 memoryStream.Position = 0L;
28 office 157  
36 office 158 var result = Encoding.ASCII.GetString(memoryStream.ToArray());
28 office 159  
54 office 160 Parallel.ForEach(result.Split(Radios.Yaesu.FT_891.Constants.Eot),
161 new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
162 async (split, state) =>
36 office 163 {
54 office 164 if (string.IsNullOrEmpty(split)) state.Stop();
28 office 165  
54 office 166 try
28 office 167 {
54 office 168 switch (_catAssemblies.CatParse<BusyState>("BY",
169 new object[] { $"{split}{Radios.Yaesu.FT_891.Constants.Eot}" }))
170 {
171 case BusyState.ON:
172 if (_configuration.Notifications.TryGetNotificationState(
173 NotificationType.SignalScanDetect, out var notificationState))
174 state.Stop();
36 office 175  
54 office 176 var toastFrom = new ToastForm(
177 $"{Resources.Signal_detected_during_scan}",
178 $"{Resources.Frequency}: {_currentFrequency}Hz",
179 notificationState.LingerTime,
180 Constants.AssemblyIcon);
36 office 181  
54 office 182 toastFrom.Show();
36 office 183  
54 office 184 await Task.Delay(
185 TimeSpan.FromSeconds(bandScanParameters.PauseDetectTime),
186 _scanningCancellationToken);
187 state.Stop();
188 break;
189 }
28 office 190 }
54 office 191 catch (TargetInvocationException exception) when
192 (exception.InnerException is UnmatchedRadioResponseException)
193 {
194 // suppress
195 }
196 catch (Exception exception)
197 {
198 Log.Warning(exception, Resources.Error_encountered_while_scanning_for_signal);
199 }
200 });
9 office 201 }
202 }
54 office 203 catch (Exception exception)
36 office 204 {
205 Log.Warning(exception, Resources.Error_encountered_while_scanning_for_signal);
206 }
207 finally
208 {
209 _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.OFF });
210 }
9 office 211  
36 office 212 _currentFrequency = _currentFrequency + bandScanParameters.StepFrequency;
54 office 213 if (_currentFrequency > _maxFrequency) _currentFrequency = _minFrequency;
214 if (_currentFrequency < _minFrequency) _currentFrequency = _minFrequency;
36 office 215 } while (!_scanningCancellationToken.IsCancellationRequested);
3 office 216 }
36 office 217 catch (Exception exception)
3 office 218 {
219 Log.Error(exception, Resources.Scanning_aborted);
220 }
9 office 221 finally
222 {
223 if (_serialPort.IsOpen)
224 {
225 _serialPort.Close();
226  
227 _serialPort.DiscardInBuffer();
228 }
229 }
3 office 230 }
231 }
54 office 232 }