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