HamBook – Rev 14

Subversion Repositories:
Rev:
using HamBook.Radios.Generic;
using HamBook.Radios;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Serilog;
using HamBook.Properties;
using Serilog.Events;
using System.Media;
using System.Reflection;
using RJCP.IO.Ports;
using System.Diagnostics;
using System.IO;
using Toasts;
using System.Drawing;
using Configuration;

namespace HamBook
{
    public class BandScan
    {
        private CancellationTokenSource _scanningCancellationTokenSource;

        private CancellationToken _scanningCancellationToken;
        private CatAssemblies _catAssemblies;
        private int _minFrequency;
        private int _maxFrequency;
        private SerialPortStream _serialPort;
        private Configuration.Configuration _configuration;
        private int _currentFrequency;
        private Task _scanTask;

        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 step, int pause, int detect)
        {
            _scanningCancellationTokenSource = new CancellationTokenSource();
            _scanningCancellationToken = _scanningCancellationTokenSource.Token;

            _scanTask = Scan(step, pause, detect);
        }

        public async Task Stop()
        {
            if (_scanningCancellationTokenSource != null)
            {
                _scanningCancellationTokenSource.Cancel();
            }

            if(_scanTask != null)
            {
                await _scanTask;
                _scanTask = null;
            }
        }

        private async Task Scan(int step, int pause, int detect)
        {
            if (!_serialPort.IsOpen)
            {
                _serialPort.Open();
            }

            _serialPort.DiscardInBuffer();

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

            try
            {

                _currentFrequency = _minFrequency;

                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(pause), _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

                    using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
                    {
                        soundPlayer.Play();
                        await _catAssemblies.CatWriteAsync<int>("FA", new object[] { _currentFrequency }, _scanningCancellationToken);
                    }

                    using (var memoryStream = new MemoryStream())
                    {
                        _serialPort.DiscardInBuffer();

                        await taskCompletionSource.Task;

                        var count = _serialPort.BaudRate / sizeof(byte) * pause;
                        await _serialPort.CopyToAsync(memoryStream, count, _scanningCancellationToken);

                        memoryStream.Position = 0L;

                        // TODO: radios
                        var result = Encoding.ASCII.GetString(memoryStream.ToArray());
                        foreach (var split in result.Split(Radios.Generic.Constants.EOT))
                        {
                            var command = $"{split}{Radios.Generic.Constants.EOT}";

                            switch (_catAssemblies.CatParse<BusyState>("BY", new object[] { command }))
                            {
                                case BusyState.ON:
                                    if (!_configuration.Notifications.TryGetNotificationState(NotificationType.SignalScanDetect, out var notificationState))
                                    {
                                        var toastFrom = new ToastForm(
                                            $"{Resources.Signal_detected_during_scan}",
                                            $"{Resources.Frequency}: {_currentFrequency}Hz",
                                            notificationState.LingerTime,
                                            Constants.AssemblyIcon);

                                        toastFrom.Show();

                                        await Task.Delay(TimeSpan.FromSeconds(detect), _scanningCancellationToken);
                                    }
                                    continue;
                            }
                        }
                    }

                    _currentFrequency = _currentFrequency + step;
                    if(_currentFrequency > _maxFrequency)
                    {
                        _currentFrequency = _minFrequency;
                    }
                    if(_currentFrequency < _minFrequency)
                    {
                        _currentFrequency = _minFrequency;
                    }

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

                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();

                    _serialPort.DiscardInBuffer();
                }
            }
        }
    }
}