HamBook – Rev 46

Subversion Repositories:
Rev:
using HamBook.Radios.Generic;
using HamBook.Radios.Generic.CAT;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static HamBook.Radios.Yaesu.FT_891.Constants;
using RJCP.IO.Ports;
using System.Threading;
using System.Diagnostics;

namespace HamBook.Radios.Yaesu.FT_891.CAT
{
    [Radio("Yaesu FT-891")]
    public class PS : HamBook.Radios.Generic.CAT.PS
    {
        private readonly Regex readRegex;

        public override CatLength CatLength => new CatLength { Set = 4, Answer = 4, Read = 3 };

        public PS(SerialPortStream serialPort) : base(serialPort)
        {
            readRegex = new Regex($"^{Name}(?<state>[01]){Constants.EOT}$", RegexOptions.Compiled);
        }

        public override async Task<bool> SetAsync(PowerState state, CancellationToken cancellationToken)
        {
            SerialPort.Write(new byte[1] { 0 }, 0, 1);
            SerialPort.Read(new byte[2] { 0, 0 }, 0, 2);

            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(POWER_ON_DELAY).ContinueWith(async task1 =>
            {
                byte[] payload = null;
                switch(state)
                {
                    case PowerState.ON:
                        payload = Constants.Encoding.GetBytes($"{Name}1{Constants.EOT}");
                        await SerialPort.WriteAsync(payload, 0, payload.Length);
                        Task.Delay(TIME_TO_WARM).ContinueWith(task2 =>
                        {
                            taskCompletionSource.TrySetResult(true);
                        });
                        return;
                    case PowerState.OFF:
                        payload = Constants.Encoding.GetBytes($"{Name}0{Constants.EOT}");
                        await SerialPort.WriteAsync(payload, 0, payload.Length);
                        break;
                }
                taskCompletionSource.TrySetResult(true);
            });
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

            await taskCompletionSource.Task;
            return await ReadAsync(cancellationToken) == state;
        }

        public override async Task<PowerState> ReadAsync(CancellationToken cancellationToken)
        {
            SerialPort.Write(new byte[1] { 0 }, 0, 1);
            SerialPort.Read(new byte[2] { 0, 0 }, 0, 2);

            var taskCompletionSource = new TaskCompletionSource<int>();

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            Task.Delay(POWER_ON_DELAY).ContinueWith(async _ =>
            {
                var payload = Constants.Encoding.GetBytes($"{Name}{Constants.EOT}");

                await SerialPort.WriteAsync(payload, 0, payload.Length, cancellationToken);

                var buffer = new byte[CatLength.Answer];
                if (await SerialPort.ReadAsync(buffer, 0, CatLength.Answer, cancellationToken) != CatLength.Answer)
                {
                    taskCompletionSource.TrySetResult(-1);

                    throw new UnexpectedRadioResponseException(Name, buffer);
                }
                var answer = Constants.Encoding.GetString(buffer);
                var match = readRegex.Match(answer);
                if (!match.Success)
                {
                    taskCompletionSource.TrySetResult(-1);

                    throw new UnmatchedRadioResponseException(Name, answer);
                }

                var state = int.Parse(match.Result("${state}"));
                taskCompletionSource.TrySetResult(state);

            });
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            var onoff = await taskCompletionSource.Task;
            switch(onoff)
            {
                case 1:
                    return PowerState.ON;
                case 0:
                    return PowerState.OFF;
            }

            return PowerState.NONE;
        }
    }
}