trim HttpHeaders
石头 编写于 2024-06-22 08:55:23
X
using System;
using System.Linq;
using System.IO.Ports;
using System.Text;
using System.Threading;
using NewLife;
using NewLife.Log;
using NewLife.Threading;

namespace XCom
{
    class Com : DisposeBase
    {
        #region 属性
        private SerialPort _Serial;
        /// <summary>串口</summary>
        public SerialPort Serial { get { return _Serial; } set { _Serial = value; } }

        private Int32 _BytesOfReceived;
        /// <summary>收到字节数</summary>
        public Int32 BytesOfReceived { get { return _BytesOfReceived; } set { _BytesOfReceived = value; } }

        private Int32 _BytesOfSent;
        /// <summary>已发送字节数</summary>
        public Int32 BytesOfSent { get { return _BytesOfSent; } set { _BytesOfSent = value; } }

        private Encoding _Encoding = Encoding.Default;
        /// <summary>编码</summary>
        public Encoding Encoding { get { return _Encoding; } set { _Encoding = value; } }
        #endregion

        #region 构造
        TimerX tx;

        protected override void OnDispose(bool disposing)
        {
            base.OnDispose(disposing);

            if (_Serial != null && _Serial.IsOpen)
            {
                var sp = _Serial;
                _Serial = null;
                try
                {
                    sp.Close();
                    sp.Dispose();
                }
                catch { }
            }

            if (tx != null) tx.Dispose();
        }
        #endregion

        #region 方法
        public Com Open()
        {
            if (!Serial.IsOpen)
            {
                Serial.Open();

                var t = 1 * 1000;
                tx = new TimerX(s =>
                {
                    // 如果串口已关闭,则销毁
                    if (_Serial != null && !_Serial.IsOpen)
                    {
                        XTrace.WriteLine("串口已关闭,自动销毁!");
                        Dispose();
                    }
                    else
                    {
                        // 如果串口不存在,也销毁
                        var ports = SerialPort.GetPortNames();
                        if (ports == null || ports.Length < 1 || !ports.Contains(Serial.PortName))
                        {
                            XTrace.WriteLine("串口已经不存在,自动销毁!");
                            Dispose();
                        }
                    }
                }, null, t, t);
            }

            return this;
        }

        public void Write(String str) { Write(Encoding.GetBytes(str)); }

        /// <summary>写入数据</summary>
        /// <param name="buffer">缓冲区</param>
        /// <param name="offset">偏移</param>
        /// <param name="count">数量</param>
        public void Write(Byte[] buffer, Int32 offset = 0, Int32 count = -1)
        {
            Open();

            WriteLog("Write:{0}", BitConverter.ToString(buffer));

            if (count < 0) count = buffer.Length - offset;

            var sp = Serial;
            lock (sp)
            {
                _BytesOfSent += count;

                sp.Write(buffer, offset, count);
            }
        }

        public String ReadString()
        {
            var buf = new Byte[10240];
            var size = Read(buf);
            if (size <= 0) return null;

            return Encoding.GetString(buf, 0, size);
        }

        /// <summary>从串口中读取指定长度的数据,一般是一帧</summary>
        /// <param name="buffer">缓冲区</param>
        /// <param name="offset">偏移</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public Int32 Read(Byte[] buffer, Int32 offset = 0, Int32 count = -1)
        {
            Open();

            if (count < 0) count = buffer.Length - offset;

            // 读取数据
            var bufstart = offset;
            var bufend = offset + count;
            var sp = Serial;
            lock (sp)
            {
                // 等待1秒,直到有数据为止
                var timeout = sp.ReadTimeout;
                if (timeout <= 0) timeout = 100;

                var end = DateTime.Now.AddMilliseconds(timeout);
                while (sp.BytesToRead <= 0 && sp.IsOpen && end > DateTime.Now) Thread.SpinWait(1);

                try
                {
                    var size = sp.BytesToRead;
                    // 计算还有多少可用空间
                    if (offset + size > bufend) size = bufend - offset;
                    var data = new Byte[size];
                    size = sp.Read(data, 0, data.Length);
                    if (size > 0)
                    {
                        buffer.Write(offset, data, 0, size);
                        offset += size;
                    }

                    _BytesOfReceived += size;
                }
                catch { }
            }

            WriteLog("Read:{0}", BitConverter.ToString(buffer, bufstart, offset - bufstart));

            return offset - bufstart;
        }
        #endregion

        #region 异步接收
        /// <summary>开始监听</summary>
        public void Listen()
        {
            Open();

            Serial.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
            //serial.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
        }

        void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // 发送者必须保持一定间隔,每个报文不能太大,否则会因为粘包拆包而出错
            try
            {
                var sp = sender as SerialPort;
                var count = 0;
                while (sp.BytesToRead > count)
                {
                    count = sp.BytesToRead;
                    // 暂停一会,可能还有数据
                    Thread.Sleep(1);
                }
                if (sp.BytesToRead > 0)
                {
                    var buf = new byte[sp.BytesToRead];
                    count = sp.Read(buf, 0, buf.Length);
                    if (count != buf.Length) buf = buf.ReadBytes(0, count);

                    if (Received != null)
                    {
                        _BytesOfReceived += buf.Length;

                        var e2 = new DataReceivedEventArgs { Data = buf };
                        Received(this, e2);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLog("Error " + ex.Message);
            }
        }

        /// <summary>数据到达事件,事件里调用<see cref="Read"/>读取数据</summary>
        public event EventHandler<DataReceivedEventArgs> Received;
        #endregion

        #region 日志
        /// <summary>输出日志</summary>
        /// <param name="formart"></param>
        /// <param name="args"></param>
        public static void WriteLog(String formart, params Object[] args)
        {
            XTrace.WriteLine(formart, args);
        }
        #endregion
    }
}