RemoteService.cs 7.1 KB
using Fleck;
using Newtonsoft.Json;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    public static class RemoteService
    {
        /// <summary>
        /// deviceGroupName
        /// </summary>
        static Dictionary<string,IWebSocketConnection> allClients;
        static WebSocketServer server;
        /// <summary>
        /// 初始化监听服务
        /// </summary>
        public static void Init() {
            FleckLog.Level = LogLevel.Debug;
            allClients = new Dictionary<string, IWebSocketConnection>();
            server = new WebSocketServer("ws://0.0.0.0:26901");
            server.RestartAfterListenError=true;
            server.Start(client =>
            {
                client.OnOpen = () =>
                {
                    var deviceGroupName = client.ConnectionInfo.Path.Substring(1);
                    LogUtil.info($"客户端OnOpen:{deviceGroupName}");
                    lock (allClients)
                    {
                        if (allClients.ContainsKey(deviceGroupName))
                            allClients[deviceGroupName]=client;
                        else
                            allClients.Add(deviceGroupName,client);
                    }
                };
                client.OnClose = () =>
                {
                    var deviceGroupName = client.ConnectionInfo.Path.Substring(1);
                    LogUtil.info($"客户端OnClose:{deviceGroupName}");
                    lock (allClients)
                    {
                        allClients.Remove(deviceGroupName);
                    }
                };
                client.OnMessage = message =>
                {
                    var deviceGroupName = client.ConnectionInfo.Path.Substring(1);
                    ProcessMessage(deviceGroupName,message);
                };
            });
        }
        static volatile Dictionary<long, RemoteResult> lastresult = new Dictionary<long, RemoteResult>();
        static void ProcessMessage(string deviceGroupName, string message) {
            bool isok = true;
            long Seq = 1;
            try
            {                
                var remoteLoad = JsonConvert.DeserializeObject<RemoteLoad>(message);
                Seq = remoteLoad.Seq;
                lock (lastresult) {
                    lastresult[Seq] = RemoteResult.None;
                }
                switch (remoteLoad.Action)
                {
                    case "SetTrayRequest":
                        TrayManager.SetTrayRequest(remoteLoad);
                        break;
                    case "TrayInfo":
                        TrayManager.TrayInfo(remoteLoad);
                        break;
                    case "TrayRelease":
                        TrayManager.TrayRelease(remoteLoad);
                        break;
                    case "IsFree":
                        isok = TrayManager.IsFree(remoteLoad);
                        break;
                    case "IsNeedProcessNG":
                        isok = TrayManager.IsNeedProcessNG(remoteLoad);
                        break;
                    case "Heartbeats": //客户端心跳包
                        isok = true;
                        break;
                    case "OK":
                    case "FAIL":
                        lock (lastresult)
                        {
                            lastresult[Seq] = remoteLoad.Action == "OK" ? RemoteResult.True : RemoteResult.False;
                        }
                        LogUtil.info($"[{remoteLoad.GroupName}] Revice Command Callback:" + remoteLoad.Action);
                        return;
                    default:
                        break;
                }
            }
            catch(Exception e) {
                isok = false;
                LogUtil.info("Remote process error:"+e.ToString());
            }
            SendResult(deviceGroupName, isok, Seq);
        }
        /// <summary>
        /// 发送消息,不接收返回信息
        /// </summary>
        /// <param name="deviceGroupName">设备ID</param>
        /// <param name="message"></param>
        public static void SendMessage(string deviceGroupName,RemoteLoad message) {
            if (!allClients.ContainsKey(deviceGroupName))
            {
                LogUtil.info($"设备:{deviceGroupName} 不在线");
                return;
            }
            try
            {
                allClients[deviceGroupName].Send(JsonConvert.SerializeObject(message));
            }
            catch (Exception ex){
                LogUtil.error($"设备:{deviceGroupName} 消息发送出错:"+ex.ToString());
            }
        }

        /// <summary>
        /// 发送并等待返回
        /// </summary>
        /// <param name="GroupName">设备ID</param>
        /// <param name="remoteLoad">载荷信息</param>
        /// <param name="waittime">等待时间默认3000毫秒</param>
        /// <returns></returns>
        public static RemoteResult SendAndWait(string GroupName, RemoteLoad remoteLoad, int waittime = 3000)
        {
            remoteLoad.GroupName = GroupName;
            if (remoteLoad.RequestLoadInfo != null && string.IsNullOrEmpty(remoteLoad.RequestLoadInfo.DeviceGroupName))
                remoteLoad.RequestLoadInfo.DeviceGroupName = GroupName;
            LogUtil.info($"[{GroupName}],发送:{remoteLoad.Action},Seq:{remoteLoad.Seq}");
            lock (lastresult)
            {
                lastresult[remoteLoad.Seq] = RemoteResult.None;
            }
            SendMessage(GroupName, remoteLoad);
            return WaitResult(GroupName, remoteLoad.Seq,waittime);
        }
        static RemoteResult WaitResult(string GroupName,long seq,int waittime = 3000)
        {
            if (!lastresult.ContainsKey(seq))
                return RemoteResult.Timeout;
            try
            {
                while (lastresult[seq] == RemoteResult.None && waittime > 0)
                {
                    System.Threading.Thread.Sleep(50);
                    waittime = waittime - 50;
                }
                if (lastresult[seq] == RemoteResult.None)
                {
                    LogUtil.info($"等待{GroupName}反馈超时 seq:" + seq);
                    lastresult[seq] = RemoteResult.Timeout;
                }

                var result = lastresult[seq];
                lock (lastresult)
                {
                    lastresult.Remove(seq);
                }
                return result;
            }
            catch(Exception ex) {
                LogUtil.error($"等待{GroupName}反馈超时 seq:" + seq +" 出错:"+ex);
                return RemoteResult.Timeout;
            }
        }
        static void SendResult(string deviceGroupName, bool result,long Seq)
        {
            RemoteLoad remoteLoad = new RemoteLoad();
            remoteLoad.Seq = Seq;
            remoteLoad.Action = result?"OK":"FAIL";
            remoteLoad.GroupName = deviceGroupName;
            SendMessage(deviceGroupName, remoteLoad);
        }
       
    }

}