HamBook – Rev 61

Subversion Repositories:
Rev:
using System;
using System.IO;
using System.Media;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Configuration;
using HamBook.Properties;
using HamBook.Radios;
using HamBook.Radios.Generic;
using RJCP.IO.Ports;
using Serilog;
using Toasts;
using static System.Windows.Forms.AxHost;
using Toasts = Toasts.Toasts;

namespace HamBook
{
    public class BandScan
    {
        private readonly CatAssemblies _catAssemblies;
        private readonly Configuration.Configuration _configuration;
        private readonly int _maxFrequency;
        private readonly int _minFrequency;
        private readonly SerialPortStream _serialPort;
        private int _currentFrequency;
        private CancellationToken _scanningCancellationToken;
        private CancellationTokenSource _scanningCancellationTokenSource;
        private Thread _scanThread;
        private global::Toasts.Toasts _toasts;

        private BandScan()
        {
            
        }

        public BandScan(CatAssemblies catAssemblies, int min, int max, SerialPortStream serialPort,
            Configuration.Configuration configuration) : this()
        {
            _catAssemblies = catAssemblies;
            _minFrequency = min;
            _maxFrequency = max;
            _serialPort = serialPort;
            _configuration = configuration;
        }

        public void Start(int stepFrequency, int pauseTime, int pauseDetectTime, bool autoTune = false)
        {
            if (_scanThread != null)
            {
                if (!_scanningCancellationToken.IsCancellationRequested) _scanningCancellationTokenSource.Cancel();

                _scanThread.Join();
                _scanThread = null;
            }

            _scanningCancellationTokenSource = new CancellationTokenSource();
            _scanningCancellationToken = _scanningCancellationTokenSource.Token;

            _toasts = new global::Toasts.Toasts(_scanningCancellationToken);

            _scanThread = new Thread(Scan);
            _scanThread.Start(new BandScanParameters(stepFrequency, pauseTime, pauseDetectTime, autoTune));
        }

        public void Stop()
        {
            if (_scanThread != null)
            {
                if (!_scanningCancellationToken.IsCancellationRequested) _scanningCancellationTokenSource.Cancel();

                _scanThread.Join();
                _scanThread = null;
            }

            if (_toasts != null)
            {
                _toasts.Dispose();
                _toasts = null;
            }
        }

        private async void Scan(object obj)
        {
            var bandScanParameters = (BandScanParameters)obj;

            if (!_serialPort.IsOpen) _serialPort.Open();

            _serialPort.DiscardInBuffer();

            try
            {
                _currentFrequency = _minFrequency;

                do
                {
                    using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly()
                               .GetManifestResourceStream("HamBook.Effects.pot.wav")))
                    {
                        soundPlayer.Play();

                        await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency },
                            _scanningCancellationToken);
                    }

                    if (bandScanParameters.AutoTune)
                    {
                        await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON },
                            _scanningCancellationToken);

                        do
                        {
                            await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken);

                            try
                            {
                                var tuneState = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { },
                                    _scanningCancellationToken);

                                if (tuneState != TunerState.TUNER_ON) break;
                            }
                            catch (Exception)
                            {
                                // retry
                            }
                        } while (!_scanningCancellationToken.IsCancellationRequested);

                        await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START },
                            _scanningCancellationToken);

                        do
                        {
                            await Task.Delay(TimeSpan.FromSeconds(1), _scanningCancellationToken);

                            try
                            {
                                var tuneState = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { },
                                    _scanningCancellationToken);

                                if (tuneState != TunerState.TUNING_START) break;
                            }
                            catch (Exception)
                            {
                                // retry
                            }
                        } while (!_scanningCancellationToken.IsCancellationRequested);
                    }

                    await _catAssemblies.CatWriteAsyncManual<InformationState>("AI", new object[] { InformationState.ON }, _scanningCancellationToken);

                    try
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            do
                            {
                                var taskCompletionSource = new TaskCompletionSource<bool>();

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                                Task.Delay(TimeSpan.FromSeconds(bandScanParameters.PauseTime), _scanningCancellationToken)
                                    .ContinueWith(_ => taskCompletionSource.TrySetResult(true), CancellationToken.None);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

                                await taskCompletionSource.Task;

                                memoryStream.Position = 0L;

                                await _serialPort.CopyToAsync(memoryStream, _serialPort.BytesToRead,
                                    _scanningCancellationToken);

                                var signal = false;
                                var result = Encoding.ASCII.GetString(memoryStream.ToArray());
                                foreach (var split in result.Split(Radios.Yaesu.FT_891.Constants.Eot))
                                {
                                    if (!_catAssemblies.CatParse<BusyState>("BY",
                                            new object[] { $"{split}{Radios.Yaesu.FT_891.Constants.Eot}" },
                                            out var busyState))
                                    {
                                        continue;
                                    }

                                    if (busyState == BusyState.ON)
                                    {
                                        signal = true;
                                    }
                                }


                                if (!signal)
                                {
                                    break;
                                }

                                if (!_configuration.Notifications.TryGetNotificationState(
                                        NotificationType.SignalScanDetect, out var notificationState) ||
                                    !notificationState.Enabled)
                                {
                                    continue;
                                }

                                var toastFrom = new ToastForm(
                                    $"{Resources.Signal_detected_during_scan}",
                                    $"{Resources.Frequency}: {_currentFrequency}Hz")
                                {
                                    LingerTime = notificationState.LingerTime,
                                    Icon = Constants.AssemblyIcon
                                };

                                System.Windows.Forms.Application.Run(toastFrom);

                            } while (!_scanningCancellationToken.IsCancellationRequested);
                        }
                    }
                    catch (Exception exception)
                    {
                        Log.Warning(exception, Resources.Error_encountered_while_scanning_for_signal);
                    }
                    finally
                    {
                        await _catAssemblies.CatWriteAsyncManual<InformationState>("AI", new object[] { InformationState.OFF }, _scanningCancellationToken);
                    }

                    _currentFrequency = _currentFrequency + bandScanParameters.StepFrequency;

                    if (_currentFrequency > _maxFrequency) _currentFrequency = _minFrequency;
                    if (_currentFrequency < _minFrequency) _currentFrequency = _minFrequency;

                } while (!_scanningCancellationToken.IsCancellationRequested);
            }
            catch (Exception exception)
            {
                Log.Error(exception, Resources.Scanning_aborted);
            }
            finally
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();

                    _serialPort.DiscardInBuffer();
                }
            }
        }
    }
}

Generated by GNU Enscript 1.6.5.90.