ServerCommunication.cs 8.9 KB
using BLL;
using Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using OnlineStore.Common.util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BLL
{
    public class ServerCommunication
    {
        public StoreStatus status = StoreStatus.Online;
        static string server = BLLCommon.config.SmfServer;
        static string CID = BLLCommon.config.CID;
        List<EquipMsg> msgList = new List<EquipMsg>();
        int StoreID = 1;
        string StoreName = "";

        string WarnMsg = "";
        private System.Timers.Timer serverConnectTimer = new System.Timers.Timer();

        object serverclock = new object();
        public ServerCommunication()
        {            
            server = BLLCommon.config.SmfServer;
            CID = BLLCommon.config.CID;
            //Common.config.Save();
            if (server.ToLower().StartsWith("http"))
            {
                readLazyData();
                serverConnectTimer.Interval = 1000;
                serverConnectTimer.AutoReset = true;
                serverConnectTimer.Enabled = true;
                serverConnectTimer.Elapsed += ServerConnectTimer_Elapsed;
                GC.KeepAlive(serverConnectTimer);
            }
        }
        ~ServerCommunication()
        {
            while (Datalist.TryDequeue(out var msg))
            {
                backupdata(msg);
            }
        }
        private void ServerConnectTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!Monitor.TryEnter(serverConnectTimer))
                return;
            try
            {
                //ProcessMsg(Msg.msg);
                SendStatus();
            }
            catch
            {

            }
            finally
            {
                Monitor.Exit(serverConnectTimer);
            }
        }
        public void StartConnectServer()
        {
            serverConnectTimer.Enabled = true;
        }
        public void StopConnectServer()
        {
            serverConnectTimer.Enabled = false;
        }
        /// <summary>
        /// 获取整个料仓的状态
        /// </summary>
        Operation getStatus()
        {
            //构建发送给服务器的对象
            Operation Operation = new Operation();
            Operation.cid = CID;
            Operation.seq = nextSeq();
            Operation.status = status;


            if (showMsglist.TryDequeue(out var msg))
            {
                Operation.msgList.Add(msg);
            }

            while (Datalist.TryDequeue(out var msg1))
            {
                Operation.msgList.Add(msg1);
            }
            return Operation;
        }
        private static string api_communication = "/service/equipment/communication";    //流水线状态通信接口
        public static string GetPostApi()
        {
            var host = server;
            if (!host.StartsWith("http://"))
            {
                host = "http://" + host;
            }
            if (!host.EndsWith("/"))
            {
                host = host + "/";
            }
            host= host.TrimEnd('/');
            if (!Uri.TryCreate(host + api_communication, UriKind.Absolute, out Uri u)) {
                throw new Exception("Smf服务器地址配置错误:"+ host);
            }
            return u.ToString();
        }
        public void SendStatus()
        {
            if (!server.ToLower().StartsWith("http"))
                return;
            lock (serverclock)
            {
                DateTime time = DateTime.Now;
                //构建发送给服务器的对象
                Operation lineOperation = getStatus();
                lineOperation.data = lineOperation.data.Union(UnifiedDataHandler.PrintNgMESData()).ToDictionary(x => x.Key, x => x.Value);
                lineOperation.data.Add("inShelfStatus", "NONE");
                lineOperation.data.Add("outShelfStatus", "NONE");
                var returntxt = Http.PostJson(GetPostApi(), new Dictionary<string, string>(), lineOperation,900,false);
                Operation resultOperation = JsonConvert.DeserializeObject<Operation>(returntxt);
                if (resultOperation==null)
                {
                    lineOperation.msgList.ForEach(m =>
                    {
                        if (m.type == msgType.DATA)
                        {
                            backupdata(m);
                            LogNet.log.Warn("Data发送到SMF失败:"+m.msg);
                        }
                    });         
                }
                ResultProcess(resultOperation);
            }

        }
        private static int seq = 1;

        public static int nextSeq()
        {
            if (seq.Equals(Int32.MaxValue))
            {
                LogNet.log.Info("seq当前值:" + seq + ",重置seq=0");
                seq = 0;
            }
            Interlocked.Increment(ref seq);
            return seq;
        }
        public void ShowMsg(string msg,int keepsec=1, msgType _msgType = msgType.INFO) 
        {
            while (showMsglist.TryDequeue(out _)) ;

            var m = new EquipMsg();
            m.module = "NEOSCAN";
            m.type = _msgType;
            m.msg = msg;
            for (int i=0;i<keepsec;i++)
                showMsglist.Enqueue(m);
        }
        public void SendData(object data) {
            if (!server.ToLower().StartsWith("http"))
                return;
            var m = new EquipMsg();
            m.module = "NEOSCAN";
            m.type = msgType.DATA;
            m.msg = JsonConvert.SerializeObject(data);
            Datalist.Enqueue(m);
        }
        const string lazyuploaddatafile = "Retrospect\\lazyuploaddata.txt";
        void backupdata(EquipMsg msg) {            
            File.AppendAllText(lazyuploaddatafile, msg.msg+"\r\n");
        }
        void readLazyData() {
            if (!File.Exists(lazyuploaddatafile))
                return;
            var list = File.ReadAllLines(lazyuploaddatafile).ToList();
            list.ForEach(x => { SendData(x); });
            File.Delete(lazyuploaddatafile);            
        }
        ConcurrentQueue<EquipMsg> showMsglist = new ConcurrentQueue<EquipMsg>();
        ConcurrentQueue<EquipMsg> Datalist = new ConcurrentQueue<EquipMsg>();
        void ResultProcess(Operation resultOperation)
        {
            //发送状态信息到服务器 
            if (resultOperation == null)
            {
                //判断服务端是否返回出库操作
                return;
            }
        }
    }
    public class ResultData
    {
        //{"code":0,"msg":"ok","data":"7"} 
        public int code { get; set; }

        public string msg { get; set; }

        public Dictionary<string, string> data { get; set; }
    }

    /// <summary>
    ///1=设备联机(正常就绪)(入库后,BOX恢复原始状态)(出库后,移载装置恢复原始状态),
    ///2=急停,3=故障,4=警告,5=调试
    /// 6=入库执行中,7=入仓完成,8=入仓失败
    /// 9=出库执行,10=出仓完成,11=出库失败
    /// </summary>
    public enum StoreStatus
    {
        /// <summary>
        /// 1=设备联机(正常就绪)(入库后,BOX恢复原始状态)(出库后,移载装置恢复原始状态),
        /// </summary>
        Online = 1,
        /// <summary>
        ///2=急停中
        /// </summary>
        SuddenStop = 2,
        /// <summary>
        /// 3=故障中
        /// </summary>
        InTrouble = 3,
        /// <summary>
        /// 4=警告
        /// </summary>
        Warning = 4,
    }

    public class LineOperation
    {
        //  //{"result":"0","msg":"","pos":"11#AC1_18_4_28","barcode":"R506072019102200414","cid":"line-ac-11"}
        //    返回: {"code": 0, "msg":"ok", data:7}
        /// <summary>
        /// 0=成功
        /// </summary>
        public int result;
        public string cid;
        public string msg = "";
        public string pos = "";
        public string barcode = "";

    }
    /// <summary>
    /// 与服务器通信用对象
    /// </summary>
    public class Operation
    {
        public string cid;
        public string type = "NEOSCAN";  //COUNTING
        public StoreStatus status;
        public int seq;
        public int op;
        public List<EquipMsg> msgList = new List<EquipMsg>();
        public Dictionary<string, string> data = new Dictionary<string, string>();
    }

    public class EquipMsg {
        public string module;
        [JsonConverter(typeof(StringEnumConverter))]
        public msgType type;
        public string msgCode;
        public string msg;
        public List<string> msgParams = new List<string>();
    }

    public enum msgType
    {
        INFO,
        WARING,
        ERROR,
        DATA
    }

}