GComm_SerialPort.cs 5.21 KB
Newer Older
1

潘栩锋's avatar
潘栩锋 committed
2
using NLog;
潘栩锋's avatar
潘栩锋 committed
3
using System;
4
using System.Collections.Generic;
潘栩锋's avatar
潘栩锋 committed
5 6
using System.ComponentModel;
using System.IO.Ports;
7 8
using System.Linq;
using System.Text;
潘栩锋's avatar
潘栩锋 committed
9 10 11
using System.Threading;
using System.Threading.Tasks;

12
namespace GeneralGommunication
潘栩锋's avatar
潘栩锋 committed
13
{
14
    public class GComm_SerialPort : IGeneralComm
潘栩锋's avatar
潘栩锋 committed
15
    {
潘栩锋's avatar
潘栩锋 committed
16
        public Logger logger;// = NLog.LogManager.GetCurrentClassLogger();
潘栩锋's avatar
潘栩锋 committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
        /// <summary>
        /// 串口号
        /// </summary>
        public string Addr { get; set; }

        /// <summary>
        /// 是否异常
        /// </summary>
        public bool IsError => !string.IsNullOrEmpty(ErrMsg);

        /// <summary>
        /// 异常信息
        /// </summary>
        public string ErrMsg { get; private set; }

        /// <summary>
        /// Open 成功
        /// </summary>
        public bool IsConnected { get; private set; }

        /// <summary>
        /// 运行中
        /// </summary>
        public bool IsRunning { get; private set; }

        /// <summary>
        /// 接收task调用
        /// </summary>
45
        public event IGeneralCommDataReceivedHandler DataReceived;
潘栩锋's avatar
潘栩锋 committed
46 47 48 49 50 51 52

        public event PropertyChangedEventHandler PropertyChanged;


        SerialPort sp;
        CancellationTokenSource cancellation;

53
        public GComm_SerialPort()
潘栩锋's avatar
潘栩锋 committed
54
        {
55 56 57 58
            //sp = new SerialPort();
            //sp.BaudRate = 19200;
            //sp.Parity = Parity.None;
            //sp.StopBits = StopBits.One;
潘栩锋's avatar
潘栩锋 committed
59 60

        }
61 62 63 64
        public void Init(SerialPort serialPort)
        {
            this.sp = serialPort;
        }
65
        public void Write(IEnumerable<byte> buf)
潘栩锋's avatar
潘栩锋 committed
66 67 68 69 70
        {
            if (!IsConnected)
                return;
            try
            {
71 72
                var buffer = buf.ToArray();
                sp.Write(buffer, 0, buffer.Length);
潘栩锋's avatar
潘栩锋 committed
73
                logger?.Debug($"serial W len={buffer.Length}");
潘栩锋's avatar
潘栩锋 committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
                ErrMsg = null;
            }
            catch (Exception e)
            {
                ErrMsg = e.Message;
                IsConnected = false;
            }
        }

        void OnTask()
        {
            while (!cancellation.IsCancellationRequested)
            {
                ConnectTask();

                if (IsConnected)
                {
                    //进入接收task
                    ReceiveTask();
                }

                //休息一会儿,在重连
                try
                {
                    Task.Delay(2000, cancellation.Token).Wait();
                }
                catch (Exception e)
                {
                    //被打断了
                    break;
                }
            }

            IsConnected = false;
        }
        /// <summary>
        /// 连接任务
        /// </summary>
        void ConnectTask()
        {
            sp.PortName = Addr;

            while (!cancellation.IsCancellationRequested)
            {
                try
                {
                    sp.Open();
                    IsConnected = true;
                    ErrMsg = null;
                    return;
                }
                catch (Exception e)
                {
                    //连接出错
                    //等待重试
                    ErrMsg = e.Message;
                }

                try
                {
                    Task.Delay(2000, cancellation.Token).Wait();
                }
                catch (Exception e)
                {
                    //被打断
                    return;
                }
            }
        }

        /// <summary>
        /// 接收任务
        /// </summary>
        void ReceiveTask()
        {
            sp.DataReceived += Sp_DataReceived;

            while (!cancellation.IsCancellationRequested)
            {
                if (!IsConnected)
                    break;

                try
                {
                    Task.Delay(1000, cancellation.Token).Wait();
                }
                catch (Exception e)
                {
                    //被打断了
                    break;
                }
            }

            sp.DataReceived -= Sp_DataReceived;
        }


        public void Start()
        {
            if (IsRunning)
                return;
            IsRunning = true;

            sp.PortName = Addr;
            cancellation = new CancellationTokenSource();
            Task.Factory.StartNew(OnTask, cancellation.Token);
        }

        private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int bytesToRead = sp.BytesToRead;
            if (bytesToRead <= 0)
                return;
            byte[] recBuf = new byte[bytesToRead];
            sp.Read(recBuf, 0, bytesToRead);
潘栩锋's avatar
潘栩锋 committed
189
            logger?.Debug($"serial R len={bytesToRead}");
190
            DataReceived?.Invoke(this, recBuf);
潘栩锋's avatar
潘栩锋 committed
191 192 193 194 195 196 197
        }

        public void Stop()
        {
            if (!IsRunning)
                return;
            IsRunning = false;
198
            IsConnected = false;
潘栩锋's avatar
潘栩锋 committed
199 200 201 202
            cancellation.Cancel();
            sp.Close();
        }

203 204 205 206 207 208 209
        /// <summary>
        /// 清空输入缓存
        /// </summary>
        public void DiscardInBuffer() 
        {
            if (sp == null)
                return;
潘栩锋's avatar
潘栩锋 committed
210

211 212
            sp.DiscardInBuffer();
        }
潘栩锋's avatar
潘栩锋 committed
213 214
    }
}