RemoteClient.cs 5.4 KB
using log4net;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

public class RemoteClient
{
    public string GroupName;
    public string Serveraddr;
    WebSocket4Net.WebSocket webSocket;
    readonly ILog LOGGER = LogManager.GetLogger("RollingLogFileAppender");
    System.Timers.Timer timer;
    public RemoteClient( string groupName, string serveraddr)
    {
        GroupName = groupName;
        Serveraddr = serveraddr;
        timer = new System.Timers.Timer(2000);
        timer.Enabled = false;
        timer.AutoReset = true;
        timer.Elapsed += Timer_Elapsed;

        webSocket = new WebSocket4Net.WebSocket(Serveraddr + GroupName);
        LOGGER.Info("webSocket:" + serveraddr + GroupName);
        webSocket.MessageReceived += WebSocket_MessageReceived;
        webSocket.Closed += WebSocket_Closed;
        webSocket.Opened += WebSocket_Opened;
        //webSocket.AutoSendPingInterval = 2;
        //webSocket.EnableAutoSendPing = true;

        LOGGER.Info("webSocket open");
        webSocket.Open();
        timer.Start();
    }

    private void WebSocket_Opened(object sender, EventArgs e)
    {
        LOGGER.Info($"Remote:{GroupName} 连接成功");
        LastState = webSocket.State;
    }

    private void WebSocket_Closed(object sender, EventArgs e)
    {
        if (LastState != webSocket.State)
        {
            LOGGER.Info($"Remote:{GroupName} 掉线了");
        }
        LastState = webSocket.State;
    }
    WebSocket4Net.WebSocketState LastState = WebSocket4Net.WebSocketState.None;
    public bool IsOnline { get => webSocket.State == WebSocket4Net.WebSocketState.Open; }
    int errstatuscounr = 0;
    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (webSocket.State == WebSocket4Net.WebSocketState.Closed)
        {
            try
            {
                LOGGER.Info($"Remote:{GroupName} 重新连接");
                webSocket.Open();
                errstatuscounr = 0;
            }
            catch { }
        }
        else if (webSocket.State == WebSocket4Net.WebSocketState.Connecting) {
            errstatuscounr++;
            if (errstatuscounr > 5) {
                LOGGER.Info($"Remote:{GroupName} Connecting 超时");
                try { webSocket.Close(); } catch { }
                webSocket.Open();
                errstatuscounr = 0;
            }
        }
    }
    volatile RemoteResult lastresult = RemoteResult.None;
    private void WebSocket_MessageReceived(object sender, WebSocket4Net.MessageReceivedEventArgs e)
    {
        bool isok = false;
        lastresult = RemoteResult.None;
        RemoteLoad remoteLoad;
        try
        {
            remoteLoad = JsonConvert.DeserializeObject<RemoteLoad>(e.Message);
        }
        catch
        {
            LOGGER.Info("Cant Deserialize remote command:" + e.Message);
            return;
        }
        switch (remoteLoad.Action)
        {
            case "OK":
            case "FAIL":
                lastresult = remoteLoad.Action == "OK" ? RemoteResult.True : RemoteResult.False;
                LOGGER.Info("Revice Command Callback:" + remoteLoad.GroupName + " -" + remoteLoad.Action + " ,Seq:" + remoteLoad.Seq);
                return;
            default:
                if (actionlist.ContainsKey(remoteLoad.Action)) {
                    LOGGER.Info("Revice remote command:" + remoteLoad.Action +",Seq:"+ remoteLoad.Seq);
                    isok= actionlist[remoteLoad.Action].Invoke(remoteLoad.RequestLoadInfo);
                }
                else
                    LOGGER.Info("unknow remote command:" + remoteLoad.Action);
                break;
        }
        SendResult(isok, remoteLoad.Seq);
    }

    Dictionary<string, Func<RequestLoadInfo, bool>> actionlist = new Dictionary<string, Func<RequestLoadInfo, bool>>();
    public void AddAction(string actionName, Func<RequestLoadInfo, bool> action)
    {
        actionlist[actionName] = action;
    }
    int timeoutCount = 0;
    RemoteResult WaitResult(int waittime=3000)
    {
        while (lastresult == RemoteResult.None && waittime > 0)
        {
            System.Threading.Thread.Sleep(50);
            waittime = waittime - 50;            
        }
        if (lastresult == RemoteResult.None)
        {
            LOGGER.Info("等待远程反馈超时");
            timeoutCount++;
            lastresult = RemoteResult.Timeout;
            if (timeoutCount > 3)
                webSocket.Close();
        }
        else {
            timeoutCount = 0;
        }
        return lastresult;
    }
    public RemoteResult SendAndWait(RemoteLoad remoteLoad, int waittime= 3000) {
        remoteLoad.Seq = DateTime.Now.Ticks;
        remoteLoad.GroupName = GroupName;
        if (remoteLoad.RequestLoadInfo != null)
        {
            if (string.IsNullOrEmpty(remoteLoad.RequestLoadInfo.DeviceGroupName))
                remoteLoad.RequestLoadInfo.DeviceGroupName = GroupName;
        }
        lastresult = RemoteResult.None;
        webSocket.Send(JsonConvert.SerializeObject(remoteLoad));
        return WaitResult(waittime);
    }
    void SendResult(bool result,long Seq)
    {
        RemoteLoad remoteLoad = new RemoteLoad();
        remoteLoad.Seq = Seq;
        remoteLoad.Action = result ? "OK" : "FAIL";
        remoteLoad.GroupName = GroupName;
        webSocket.Send(JsonConvert.SerializeObject(remoteLoad));
    }
}