HamBook – Diff between revs 28 and 36
?pathlinks?
Rev 28 | Rev 36 | |||
---|---|---|---|---|
Line 17... | Line 17... | |||
17 | using System.IO; |
17 | using System.IO; |
|
18 | using Toasts; |
18 | using Toasts; |
|
19 | using System.Drawing; |
19 | using System.Drawing; |
|
20 | using Configuration; |
20 | using Configuration; |
|
21 | using System.Security.Cryptography; |
21 | using System.Security.Cryptography; |
|
- | 22 | using Org.BouncyCastle.Crypto.Engines; |
||
Line 22... | Line 23... | |||
22 | |
23 | |
|
23 | namespace HamBook |
24 | namespace HamBook |
|
24 | { |
25 | { |
|
25 | public class BandScan |
26 | public class BandScan |
|
26 | { |
27 | { |
|
27 | private CancellationTokenSource _scanningCancellationTokenSource; |
28 | private CancellationTokenSource _scanningCancellationTokenSource; |
|
28 | private CancellationToken _scanningCancellationToken; |
- | ||
- | 29 | private CancellationToken _scanningCancellationToken; |
||
29 | |
30 | private Thread _scanThread; |
|
30 | private CatAssemblies _catAssemblies; |
31 | private CatAssemblies _catAssemblies; |
|
31 | private int _minFrequency; |
32 | private int _minFrequency; |
|
32 | private int _maxFrequency; |
33 | private int _maxFrequency; |
|
33 | private SerialPortStream _serialPort; |
34 | private SerialPortStream _serialPort; |
|
34 | private Configuration.Configuration _configuration; |
35 | private Configuration.Configuration _configuration; |
|
35 | private int _currentFrequency; |
- | ||
Line 36... | Line 36... | |||
36 | private Task _scanTask; |
36 | private int _currentFrequency; |
|
37 | |
37 | |
|
38 | private BandScan() |
38 | private BandScan() |
|
Line 47... | Line 47... | |||
47 | _serialPort = serialPort; |
47 | _serialPort = serialPort; |
|
48 | _configuration = configuration; |
48 | _configuration = configuration; |
|
Line 49... | Line 49... | |||
49 | |
49 | |
|
Line 50... | Line -... | |||
50 | } |
- | ||
51 | |
- | ||
52 | public async void Start(int stepFrequency, int pauseTime, bool autoTune = false) |
- | ||
53 | { |
- | ||
54 | if(_scanTask != null) |
- | ||
55 | { |
- | ||
56 | if (!_scanningCancellationToken.IsCancellationRequested) |
- | ||
57 | { |
- | ||
58 | _scanningCancellationTokenSource.Cancel(); |
- | ||
59 | } |
- | ||
60 | |
- | ||
61 | await _scanTask; |
- | ||
62 | _scanTask = null; |
- | ||
63 | } |
- | ||
64 | |
- | ||
65 | _scanningCancellationTokenSource = new CancellationTokenSource(); |
- | ||
66 | _scanningCancellationToken = _scanningCancellationTokenSource.Token; |
- | ||
67 | |
- | ||
68 | _scanTask = Scan(stepFrequency, pauseTime, autoTune); |
- | ||
69 | } |
50 | } |
|
70 | |
51 | |
|
71 | public async void Start(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune = false) |
52 | public void Start(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune = false) |
|
72 | { |
53 | { |
|
73 | if (_scanTask != null) |
54 | if (_scanThread != null) |
|
74 | { |
55 | { |
|
75 | if (!_scanningCancellationToken.IsCancellationRequested) |
56 | if (!_scanningCancellationToken.IsCancellationRequested) |
|
76 | { |
57 | { |
|
Line 77... | Line 58... | |||
77 | _scanningCancellationTokenSource.Cancel(); |
58 | _scanningCancellationTokenSource.Cancel(); |
|
78 | } |
59 | } |
|
79 | |
60 | |
|
Line 80... | Line 61... | |||
80 | await _scanTask; |
61 | _scanThread.Join(); |
|
81 | _scanTask = null; |
62 | _scanThread = null; |
|
Line -... | Line 63... | |||
- | 63 | } |
||
82 | } |
64 | |
|
83 | |
65 | _scanningCancellationTokenSource = new CancellationTokenSource(); |
|
Line 84... | Line 66... | |||
84 | _scanningCancellationTokenSource = new CancellationTokenSource(); |
66 | _scanningCancellationToken = _scanningCancellationTokenSource.Token; |
|
85 | _scanningCancellationToken = _scanningCancellationTokenSource.Token; |
67 | |
|
86 | |
68 | _scanThread = new Thread(new ParameterizedThreadStart(Scan)); |
|
87 | _scanTask = Scan(stepFrequency, pauseTime, pauseDetectTime, autoTune); |
69 | _scanThread.Start(new BandScanParameters(stepFrequency, pauseTime, pauseDetectTime, autoTune)); |
|
88 | } |
70 | } |
|
89 | |
71 | |
|
90 | public async Task Stop() |
72 | public async Task Stop() |
|
91 | { |
73 | { |
|
Line 92... | Line 74... | |||
92 | if (_scanTask != null) |
74 | if (_scanThread != null) |
|
93 | { |
75 | { |
|
94 | if (!_scanningCancellationToken.IsCancellationRequested) |
76 | if (!_scanningCancellationToken.IsCancellationRequested) |
|
95 | { |
77 | { |
|
Line 96... | Line 78... | |||
96 | _scanningCancellationTokenSource.Cancel(); |
78 | _scanningCancellationTokenSource.Cancel(); |
|
97 | } |
79 | } |
|
- | 80 | |
||
- | 81 | _scanThread.Join(); |
||
98 | |
82 | _scanThread = null; |
|
99 | await _scanTask; |
83 | } |
|
100 | _scanTask = null; |
84 | } |
|
101 | } |
85 | |
|
Line 102... | Line 86... | |||
102 | } |
86 | private async void Scan(object obj) |
|
Line 103... | Line -... | |||
103 | |
- | ||
104 | private async Task Scan(int stepFrequency, int pauseTime, bool autoTune) |
- | ||
105 | { |
87 | { |
|
106 | if (!_serialPort.IsOpen) |
88 | var bandScanParameters = (BandScanParameters)obj; |
|
Line 107... | Line 89... | |||
107 | { |
89 | |
|
Line 108... | Line 90... | |||
108 | _serialPort.Open(); |
90 | if (!_serialPort.IsOpen) |
|
109 | } |
91 | { |
|
110 | |
92 | _serialPort.Open(); |
|
Line 111... | Line -... | |||
111 | _serialPort.DiscardInBuffer(); |
- | ||
112 | |
- | ||
113 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
- | ||
114 | |
- | ||
115 | try |
- | ||
116 | { |
93 | } |
|
117 | |
94 | |
|
118 | _currentFrequency = _minFrequency; |
95 | _serialPort.DiscardInBuffer(); |
|
119 | |
96 | |
|
120 | do |
97 | try |
|
Line 121... | Line 98... | |||
121 | { |
98 | { |
|
122 | var taskCompletionSource = new TaskCompletionSource<bool>(); |
99 | |
|
123 | |
100 | _currentFrequency = _minFrequency; |
|
Line 124... | Line 101... | |||
124 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
101 | |
|
125 | Task.Delay(TimeSpan.FromSeconds(pauseTime), _scanningCancellationToken) |
- | ||
Line 126... | Line -... | |||
126 | .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None); |
- | ||
127 | #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
- | ||
128 | |
- | ||
129 | using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav"))) |
- | ||
130 | { |
- | ||
131 | soundPlayer.Play(); |
- | ||
132 | await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken); |
102 | do |
|
133 | } |
- | ||
134 | |
103 | { |
|
135 | if (autoTune) |
- | ||
136 | { |
- | ||
137 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _scanningCancellationToken); |
- | ||
138 | |
104 | var taskCompletionSource = new TaskCompletionSource<bool>(); |
|
139 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _scanningCancellationToken); |
- | ||
140 | } |
- | ||
141 | |
- | ||
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) |
- | ||
Line -... | Line 105... | |||
- | 105 | |
||
- | 106 | using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav"))) |
||
165 | { |
107 | { |
|
- | 108 | soundPlayer.Play(); |
||
- | 109 | await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken); |
||
- | 110 | } |
||
- | 111 | |
||
- | 112 | if (bandScanParameters.AutoTune) |
||
- | 113 | { |
||
- | 114 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _scanningCancellationToken); |
||
- | 115 | |
||
Line 166... | Line 116... | |||
166 | _serialPort.Close(); |
116 | await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _scanningCancellationToken); |
|
167 | |
117 | |
|
Line 168... | Line 118... | |||
168 | _serialPort.DiscardInBuffer(); |
118 | do |
|
Line 169... | Line 119... | |||
169 | } |
119 | { |
|
170 | } |
120 | await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken); |
|
171 | } |
121 | |
|
- | 122 | try |
||
Line 172... | Line 123... | |||
172 | |
123 | { |
|
173 | private async Task Scan(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune) |
124 | if (await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { }, _scanningCancellationToken) != TunerState.TUNING_START) |
|
174 | { |
125 | { |
|
175 | if (!_serialPort.IsOpen) |
126 | break; |
|
Line 176... | Line -... | |||
176 | { |
- | ||
177 | _serialPort.Open(); |
- | ||
178 | } |
127 | } |
|
179 | |
- | ||
180 | _serialPort.DiscardInBuffer(); |
- | ||
Line 181... | Line -... | |||
181 | |
- | ||
182 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
- | ||
183 | |
128 | } |
|
Line 184... | Line 129... | |||
184 | try |
129 | catch (Exception) |
|
185 | { |
- | ||
186 | |
- | ||
Line 187... | Line 130... | |||
187 | _currentFrequency = _minFrequency; |
130 | { |
|
Line 188... | Line 131... | |||
188 | |
131 | // retry |
|
189 | do |
132 | } |
|
190 | { |
133 | |
|
- | 134 | } while (!_scanningCancellationToken.IsCancellationRequested); |
||
- | 135 | } |
||
- | 136 | |
||
Line 191... | Line 137... | |||
191 | var taskCompletionSource = new TaskCompletionSource<bool>(); |
137 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
|
192 | |
138 | |
|
193 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
139 | try |
|
194 | Task.Delay(TimeSpan.FromSeconds(pauseTime), _scanningCancellationToken) |
140 | { |
|
- | 141 | using (var memoryStream = new MemoryStream()) |
||
- | 142 | { |
||
- | 143 | |
||
- | 144 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
||
- | 145 | Task.Delay(TimeSpan.FromSeconds(bandScanParameters.PauseTime), _scanningCancellationToken) |
||
- | 146 | .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None); |
||
- | 147 | #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
||
- | 148 | |
||
- | 149 | await taskCompletionSource.Task; |
||
- | 150 | |
||
- | 151 | await _serialPort.CopyToAsync(memoryStream, _serialPort.BytesToRead, _scanningCancellationToken); |
||
- | 152 | |
||
- | 153 | memoryStream.Position = 0L; |
||
- | 154 | |
||
- | 155 | var result = Encoding.ASCII.GetString(memoryStream.ToArray()); |
||
- | 156 | |
||
195 | .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None); |
157 | Parallel.ForEach(result.Split(Radios.Generic.Constants.EOT), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, async (split, state) => |
|
196 | #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed |
158 | { |
|
197 | |
159 | if (string.IsNullOrEmpty(split)) |
|
198 | using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav"))) |
160 | { |
|
199 | { |
161 | state.Stop(); |
|
200 | soundPlayer.Play(); |
162 | } |
|
201 | await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken); |
163 | |
|
202 | } |
- | ||
203 | |
- | ||
204 | if(autoTune) |
- | ||
205 | { |
- | ||
206 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.OFF }); |
- | ||
207 | |
- | ||
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 | } |
164 | try |
|
229 | |
- | ||
230 | } while (!_scanningCancellationToken.IsCancellationRequested); |
- | ||
231 | } |
- | ||
232 | finally |
- | ||
233 | { |
- | ||
234 | _catAssemblies.CatWrite<InformationState>("AI", new object[] { InformationState.ON }); |
165 | { |
|
235 | } |
- | ||
236 | } |
- | ||
237 | |
- | ||
238 | using (var memoryStream = new MemoryStream()) |
- | ||
239 | { |
- | ||
240 | _serialPort.DiscardInBuffer(); |
- | ||
241 | |
- | ||
242 | await taskCompletionSource.Task; |
- | ||
243 | |
- | ||
244 | var count = _serialPort.BaudRate / sizeof(byte) * pauseTime; |
- | ||
245 | await _serialPort.CopyToAsync(memoryStream, count, _scanningCancellationToken); |
- | ||
246 | |
- | ||
247 | memoryStream.Position = 0L; |
- | ||
248 | |
- | ||
249 | // TODO: radios |
166 | switch (_catAssemblies.CatParse<BusyState>("BY", new object[] { $"{split}{Radios.Generic.Constants.EOT}" })) |
|
250 | var result = Encoding.ASCII.GetString(memoryStream.ToArray()); |
- | ||
251 | foreach (var split in result.Split(Radios.Generic.Constants.EOT)) |
167 | { |
|
252 | { |
168 | case BusyState.ON: |
|
253 | if(string.IsNullOrEmpty(split)) |
- | ||
254 | { |
- | ||
255 | continue; |
- | ||
256 | } |
- | ||
257 | |
- | ||
258 | try |
- | ||
259 | { |
- | ||
260 | switch (_catAssemblies.CatParse<BusyState>("BY", new object[] { $"{split}{Radios.Generic.Constants.EOT}" })) |
- | ||
261 | { |
169 | if (_configuration.Notifications.TryGetNotificationState(NotificationType.SignalScanDetect, out var notificationState)) |
|
262 | case BusyState.ON: |
170 | { |
|
- | 171 | state.Stop(); |
||
- | 172 | } |
||
- | 173 | |
||
- | 174 | var toastFrom = new ToastForm( |
||
- | 175 | $"{Resources.Signal_detected_during_scan}", |
||
- | 176 | $"{Resources.Frequency}: {_currentFrequency}Hz", |
||
- | 177 | notificationState.LingerTime, |
||
- | 178 | Constants.AssemblyIcon); |
||
Line 263... | Line 179... | |||
263 | if (_configuration.Notifications.TryGetNotificationState(NotificationType.SignalScanDetect, out var notificationState)) |
179 | |
|
264 | { |
180 | toastFrom.Show(); |
|
265 | continue; |
181 | |
|
266 | } |
182 | await Task.Delay(TimeSpan.FromSeconds(bandScanParameters.PauseDetectTime), _scanningCancellationToken); |
|
267 | |
183 | state.Stop(); |
|
268 | var toastFrom = new ToastForm( |
184 | break; |
|
269 | $"{Resources.Signal_detected_during_scan}", |
185 | } |
|
270 | $"{Resources.Frequency}: {_currentFrequency}Hz", |
186 | } |
|
271 | notificationState.LingerTime, |
187 | catch (TargetInvocationException exception) when (exception.InnerException is UnmatchedRadioResponseException) |
|
Line 272... | Line 188... | |||
272 | Constants.AssemblyIcon); |
188 | { |
|
273 | |
189 | // suppress |
|
274 | toastFrom.Show(); |
190 | } |
|
275 | |
191 | catch (Exception exception) |
|
276 | await Task.Delay(TimeSpan.FromSeconds(pauseDetectTime), _scanningCancellationToken); |
192 | { |
|
277 | continue; |
193 | Log.Warning(exception, Resources.Error_encountered_while_scanning_for_signal); |
|
278 | } |
194 | } |
|
279 | } |
195 | }); |
|
280 | catch (TargetInvocationException exception) when (exception.InnerException is UnmatchedRadioResponseException) |
- | ||
281 | { |
- | ||
282 | // suppress |
196 | } |
|
283 | } |
197 | } |
|
284 | catch (Exception exception) |
198 | catch(Exception exception) |
|
Line 285... | Line 199... | |||
285 | { |
199 | { |