CodeFile1.cs 10.5 KB
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Asa
{
    /// <summary>
    /// X-ray Source (AVJ Technologies Company)
    /// </summary>
    public class XRay
    {
        private System.IO.Ports.SerialPort port;
        private System.Threading.Thread tSend;
        private log4net.ILog log;
        private bool warmUpComplete;
        private bool loop;
        private bool _receive;
        private byte[] _buffer;



        /// <summary>
        /// 预热事件委托
        /// </summary>
        /// <param name="state">预热完成的状态</param>
        /// <param name="text">文本</param>
        public delegate void WarmUpEvent(bool state, string text);
        /// <summary>
        /// 预热事件
        /// </summary>
        public event WarmUpEvent WarmUp;

        /// <summary>
        /// X-ray Source
        /// </summary>
        /// <param name="logName"></param>
        public XRay(string logName = "XRay")
        {
            port = new System.IO.Ports.SerialPort  //9600,N,8,1
            {
                BaudRate = 9600,
                Parity = System.IO.Ports.Parity.None,
                DataBits = 8,
                StopBits = System.IO.Ports.StopBits.One
            };
            port.DataReceived += Port_DataReceived;

            _receive = false;
            log = log4net.LogManager.GetLogger(logName);
        }

        /// <summary>
        /// 串口打开或关闭状态
        /// </summary>
        public bool IsPortOpen { get { return port.IsOpen; } }

        /// <summary>
        /// X射线打开或关闭状态
        /// </summary>
        public bool IsRayOpen { get; private set; } = false;

        /// <summary>
        /// 打开设备
        /// </summary>
        /// <param name="portName">串口名称</param>
        /// <param name="lastDate">最后使用日期</param>
        /// <returns></returns>
        public bool Open(string portName, string lastDate)
        {
            try
            {
                port.PortName = portName;
                port.Open();

                int days;
                if (string.IsNullOrWhiteSpace(lastDate))
                {
                    days = 3;
                }
                else
                {
                    DateTime lastUsed = Convert.ToDateTime(lastDate);
                    TimeSpan ts = DateTime.Now.Subtract(lastUsed);
                    days = ts.Days;
                }

                log.Info("当前距离最后使用的天数:" + days);
                loop = true;
                tSend = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(WarmUpProcess));
                tSend.Start(days);

                return port.IsOpen;
            }
            catch (Exception ex)
            {
                log.Error("Open", ex);
                return false;
            }
        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        public void Close()
        {
            port.Close();
        }

        /// <summary>
        /// 设置电压电流
        /// </summary>
        /// <param name="voltage">电压kV(除小数点外必须4位数,不够的补0,小数必须1位)</param>
        /// <param name="current">电流uA(必须4位数,没有小数,不够的补0)</param>
        public bool SetVC(string voltage, string current)
        {
            bool rtn = SendCmd("VP" + voltage);
            if (!rtn) return rtn;

            System.Threading.Thread.Sleep(500);
            rtn = SendCmd("CP" + current);
            return rtn;
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            if (!warmUpComplete) return false;
            bool rtn1 = SendCmd("ENBL0");
            loop = false;
            IsRayOpen = false;
            return rtn1;
        }

        /// <summary>
        /// 启动
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (!warmUpComplete) return false;

            bool rtn = SendCmd("ENBL1");
            if (rtn)
            {
                loop = true;
                IsRayOpen = true;
                tSend = new System.Threading.Thread(new System.Threading.ThreadStart(WatchDog));
                tSend.Start();
            }
            return rtn;
        }








        private bool SendCmd(string cmd)
        {
            byte[] temp = Encoding.ASCII.GetBytes(cmd);
            byte[] buff = new byte[temp.Length + 2];
            Array.Copy(temp, 0, buff, 1, temp.Length);

            buff[0] = 0x02;                //包头
            buff[buff.Length - 1] = 0x0D;  //包尾

            try
            {
                _receive = false;
                log.Info("Send " + cmd + " Hex: " + HexBuff(buff));
                port.Write(buff, 0, buff.Length);

                bool rtn = Wait();
                if (rtn)
                {
                    string result = "";
                    if (_buffer[0] == 0x02 && _buffer[_buffer.Length - 1] == 0x0D)
                        result = Encoding.ASCII.GetString(_buffer, 1, _buffer.Length - 2);
                    log.Info("Received " + result + " Hex: " + HexBuff(_buffer));
                }
                else
                {
                    log.Info("Received Timeout");
                }
                return rtn;
            }
            catch (Exception ex)
            {
                log.Error("SendCmd", ex);
                return false;
            }

        }

        private void Port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(50);
            byte[] temp = new byte[100];
            int count = port.Read(temp, 0, temp.Length);

            _buffer = new byte[count];
            Array.Copy(temp, 0, _buffer, 0, count);
            _receive = true;
        }

        private bool Wait()
        {
            int time = 0;
            while (time < 5000)
            {
                if (_receive) return true;
                System.Threading.Thread.Sleep(50);
                time += 50;
            }
            return false;
        }

        private string HexBuff(byte[] buff)
        {
            string s = "";
            if (buff == null) return s;

            for (int i = 0; i < buff.Length; i++)
                s += buff[i].ToString("X2") + " ";
            return s;
        }

        /// <summary>
        /// 看门狗时间,(多线程)
        /// </summary>
        private void WatchDog()
        {
            //设备在打开X光后,750ms内没有任何命令,就会关闭X光
            while (loop)
            {
                bool rtn = SendCmd("WDTE");
                if (!rtn) return;
                System.Threading.Thread.Sleep(600);
            }
        }

        /// <summary>
        /// 预热处理,(多线程)
        /// </summary>
        /// <param name="obj">天数</param>
        private void WarmUpProcess(object obj)
        {
            int days = (int)obj;
            int millisecond = 0;
            int step = 0;   //步骤
            int timer1 = 0;  //计时器
            int timer2 = 0;
            string s;
            bool rtn;
            string[] voltage = new string[10] { "030.0", "035.5", "041.1", "046.6", "052.2", "057.7", "063.3", "068.8", "074.4", "080.0" };  //电压,固定值
            string[] current = new string[10] { "0200", "0250", "0300", "0350", "0400", "0450", "0500", "0550", "0600", "0700" };            //电流,固定值
          
            if (days < 3)
                millisecond = 0;
            else if (days >= 3 && days < 30)  //3-30天
                millisecond = 30000;    //30s
            else if (days >= 30 && days < 90)  //1-3月
                millisecond = 60000;    //60s
            else if (days >= 90)  //3个月以上
                millisecond = 300000;   //300s

            if (millisecond == 0)
            {
                s = "最后使用天数小于3天,不需要预热。";
                log.Info(s);
                warmUpComplete = true;
                loop = false;
                WarmUp?.Invoke(true, s);
                return;
            }

            while (loop)
            {
                if (timer1 == 0)
                {
                    rtn = SendCmd("VP" + voltage[step]);
                    if (!rtn)
                    {
                        loop = false;
                        break;
                    }
                    System.Threading.Thread.Sleep(50);
                    rtn = SendCmd("CP" + current[step]);
                    if (!rtn)
                    {
                        loop = false;
                        break;
                    }
                    if (step == 0)  //第一步要打开平板
                    {
                        System.Threading.Thread.Sleep(50);
                        rtn = SendCmd("ENBL1");
                        if (!rtn)
                        {
                            loop = false;
                            break;
                        }
                    }
                    s = string.Format("预热{0}/10,{1}kV,{2}uA,{3}s", step + 1, voltage[step], current[step], millisecond);
                    log.Info(s);
                }

                if (timer2 == 0)
                {
                    rtn = SendCmd("WDTE");
                    if (!rtn) break;
                }

                timer1 += 100;
                timer2 += 100;

                if (timer1 >= millisecond)
                {
                    timer1 = 0;
                    step++;
                    if (step == 10)
                        loop = false;
                }

                if (timer2 >= 600)
                {
                    timer2 = 0;
                }
                System.Threading.Thread.Sleep(100);
            }

            if (step == 10)
            {
                s = "预热完成";
                log.Info(s);
                warmUpComplete = true;
                loop = false;
                WarmUp?.Invoke(true, s);
            }
            else
            {
                s = "预热未完成";
                log.Info(s);
                warmUpComplete = false;
                loop = false;
                WarmUp?.Invoke(false, s);
            }

            rtn = SendCmd("ENBL0");
        }







    }
}