using Newtonsoft.Json.Linq; using Serein.Library; using Serein.Library.Api; using Serein.Library.Network.WebSocketCommunication; using Serein.Library.Network.WebSocketCommunication.Handle; using Serein.Library.Utils; using System.Diagnostics.CodeAnalysis; namespace Serein.NodeFlow.Env { /// /// 服务端的消息管理(用于处理客户端的请求) /// [AutoSocketModule(ThemeKey = FlowEnvironment.ThemeKey, DataKey = FlowEnvironment.DataKey, MsgIdKey = FlowEnvironment.MsgIdKey)] public class MsgControllerOfServer : ISocketHandleModule { /// /// 受控环境 /// public IFlowEnvironment environment; /// /// WebSocket处理 /// public Guid HandleGuid { get; } = new Guid(); /// /// 表示是否正在控制远程 /// Local control remote env /// public bool IsLcR { get; set; } /// /// 表示是否受到远程控制 /// Remote control local env /// public bool IsRcL { get; set; } /// /// 流程环境远程管理服务 /// private WebSocketServer FlowEnvRemoteWebSocket; /// /// 启动不带Token验证的远程服务 /// public MsgControllerOfServer(IFlowEnvironment environment) { this.environment = environment; FlowEnvRemoteWebSocket ??= new WebSocketServer(); } /// /// 启动带token验证的远程服务 /// /// /// public MsgControllerOfServer(IFlowEnvironment environment, string token) { if (string.IsNullOrEmpty(token)) { SereinEnv.WriteLine(InfoType.WARN, "当前没有设置token,但使用了token验证的服务端"); } this.environment = environment; FlowEnvRemoteWebSocket ??= new WebSocketServer(token, OnInspectionAuthorized); } #region 基本方法 /// /// 启动远程 /// /// /// public async Task StartRemoteServerAsync(int port = 7525) { FlowEnvRemoteWebSocket.MsgHandleHelper.AddModule(this, (ex, send) => { send(new { code = 400, ex = ex.Message }); }); var url = $"http://*:{port}/"; try { await FlowEnvRemoteWebSocket.StartAsync(url); } catch (Exception ex) { FlowEnvRemoteWebSocket.MsgHandleHelper.RemoveModule(this); SereinEnv.WriteLine(InfoType.ERROR, "打开远程管理异常:" + ex); } } /// /// 结束远程管理 /// [AutoSocketHandle] public void StopRemoteServer() { try { FlowEnvRemoteWebSocket.Stop(); } catch (Exception ex) { SereinEnv.WriteLine(InfoType.ERROR, "结束远程管理异常:" + ex); } } /// /// 验证远程token /// /// /// private async Task OnInspectionAuthorized(dynamic token) { if (IsLcR) { return false; // 正在远程控制远程环境时,禁止其它客户端远程控制 } if (IsRcL) { return false; // 正在受到远程控制时,禁止其它客户端远程控制 } await Task.Delay(0); var tokenValue = token.ToString(); if ("123456".Equals(tokenValue)) { // 同时切换远程环境 return true; } else { return false; } } /// /// 获取发送消息的委托 /// /// private void OnResultSendMsgFunc(Func SendAsync) { // 从受控环境向主控环境发送消息。 Func func = async (theme, data) => { JObject sendJson = new JObject { [FlowEnvironment.ThemeKey] = theme, [FlowEnvironment.DataKey] = JObject.FromObject(data), }; var msg = sendJson.ToString(); await SendAsync(msg); }; // var remoteEnv = new RemoteFlowEnvironment(func); // 创建一个远程环境 // OnSwitchedEnvironment.Invoke(remoteEnv); // 通知前台切换到了远程环境 } #endregion /// /// 异步运行 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlow)] private async Task StartAsync() { var uiContextOperation = environment.IOC.Get(); var state = await environment.StartFlowAsync(); return new { state = state, }; } /// /// 从远程环境运行选定的节点 /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlowInSelectNode)] private async Task StartAsyncInSelectNode(string nodeGuid) { var state = await environment.StartAsyncInSelectNode(nodeGuid); return new { state = state, }; } /// /// 结束流程 /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.ExitFlow)] private async Task ExitFlow() { var state = await environment.ExitFlowAsync(); return new { state = state, }; } /// /// 激活全局触发器 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.ActivateFlipflopNode)] private void ActivateFlipflopNode(string nodeGuid) { environment.ActivateFlipflopNode(nodeGuid); } /// /// 关闭全局触发器 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.TerminateFlipflopNode)] private void TerminateFlipflopNode(string nodeGuid) { environment.TerminateFlipflopNode(nodeGuid); } /// /// 获取当前环境信息 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.GetEnvInfo)] private async Task GetEnvInfoAsync() { var envInfo = await environment.GetEnvInfoAsync(); return envInfo; } /// /// 加载项目文件 /// /// 环境信息 // [AutoSocketHandle(ThemeValue = EnvMsgTheme.GetProjectInfo)] private void LoadProject(FlowEnvInfo flowEnvInfo) { environment.LoadProject(flowEnvInfo, ""); } /// /// 连接远程环境 /// /// 远程环境地址 /// 远程环境端口 /// 密码 // [AutoSocketHandle] public async Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token) { return await environment.ConnectRemoteEnv(addres, port, token); } /// /// 退出远程环境 /// // [AutoSocketHandle] public void ExitRemoteEnv() { SereinEnv.WriteLine(InfoType.ERROR, "暂未实现远程退出远程环境"); IsLcR = false; } /// /// 序列化当前项目的依赖信息、节点信息 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.GetProjectInfo)] public async Task GetProjectInfoAsync() { return await environment.GetProjectInfoAsync(); } /// /// 从文件路径中加载DLL /// /// /// // [AutoSocketHandle(ThemeValue = EnvMsgTheme)] public void LoadDll(string dllPath) { } /// /// 移除DLL /// /// /// // [AutoSocketHandle(ThemeValue = EnvMsgTheme)] public bool RemoteDll(string assemblyFullName) { return false; } /// /// 从远程环境创建节点 /// /// /// /// 如果是表达式节点条件节点,该项为null [AutoSocketHandle(ThemeValue = EnvMsgTheme.CreateNode,ArgNotNull = false)] public async Task CreateNode([Needful] string nodeType, [Needful] PositionOfUI position, MethodDetailsInfo? mdInfo = null) { if (!EnumHelper.TryConvertEnum(nodeType, out var nodeControlType)) { return null; } var nodeInfo = await environment.CreateNodeAsync(nodeControlType, position, mdInfo); // 监听到客户端创建节点的请求 return nodeInfo; } /// /// 远程从远程环境移除节点 /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveNode)] public async Task RemoveNode(string nodeGuid) { var result = await environment.RemoveNodeAsync(nodeGuid); return new { state = result }; } /// /// 远程从远程环境移除节点 /// /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.PlaceNode)] public async Task PlaceNode(string nodeGuid, string containerNodeGuid) { var result = await environment.PlaceNodeToContainerAsync(nodeGuid, containerNodeGuid); return new { state = result }; } /// /// 远程从远程环境移除节点 /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.TakeOutNode)] public async Task TakeOutNode(string nodeGuid) { var result = await environment.TakeOutNodeToContainerAsync(nodeGuid); return new { state = result }; } /// /// 远程连接节点的方法调用关系 /// /// 起始节点 /// 目标节点 /// 起始节点控制点 /// 目标节点控制点 /// 连接关系 [AutoSocketHandle(ThemeValue = EnvMsgTheme.ConnectInvokeNode)] public async Task ConnectInvokeNode(string fromNodeGuid, string toNodeGuid, string fromJunctionType, string toJunctionType, string invokeType) { if (!EnumHelper.TryConvertEnum(invokeType, out var tmpConnectionType)) { return new{ state = false}; } if (!EnumHelper.TryConvertEnum(fromJunctionType, out var tmpFromJunctionType)) { return new{ state = false}; } if (!EnumHelper.TryConvertEnum(toJunctionType, out var tmpToJunctionType)) { return new{ state = false}; } // 检查控制点类别,判断此次连接请求是否符合预期 if (tmpFromJunctionType == JunctionType.Execute) { if (tmpToJunctionType == JunctionType.NextStep) { (fromNodeGuid, toNodeGuid) = (toNodeGuid, fromNodeGuid); // 需要反转 } else { return new { state = false }; // 非预期的控制点连接 } } else if (tmpFromJunctionType == JunctionType.NextStep) { if (tmpToJunctionType == JunctionType.Execute) { // 顺序正确无须反转 } else { return new { state = false }; // 非预期的控制点连接 } } else // 其它类型的控制点,排除 { return new { state = false }; // 非预期的控制点连接 } SereinEnv.WriteLine(InfoType.INFO, $"起始节点:{fromNodeGuid}"); SereinEnv.WriteLine(InfoType.INFO, $"目标节点:{toNodeGuid}"); SereinEnv.WriteLine(InfoType.INFO, $"链接请求:{(tmpFromJunctionType, tmpToJunctionType)}"); var result = await environment.ConnectInvokeNodeAsync(fromNodeGuid, toNodeGuid, tmpFromJunctionType, tmpToJunctionType, tmpConnectionType); return new { state = result }; } /// /// 远程移除节点的方法调用关系 /// /// 起始节点Guid /// 目标节点Guid /// 连接关系 [AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveInvokeConnect)] public async Task RemoveInvokeConnect(string fromNodeGuid, string toNodeGuid, string invokeType) { if (!EnumHelper.TryConvertEnum(invokeType, out var tmpConnectionType)) { return new { state = false }; } var result = await environment.RemoveConnectInvokeAsync(fromNodeGuid, toNodeGuid, tmpConnectionType); return new { state = result }; } /// /// 远程连接节点的参数传递关系 /// /// 起始节点 /// 目标节点 /// 起始节点控制点 /// 目标节点控制点 /// 入参参数来源类型 /// 第几个参数 [AutoSocketHandle(ThemeValue = EnvMsgTheme.ConnectArgSourceNode)] public async Task ConnectArgSourceNode(string fromNodeGuid, string toNodeGuid, string fromJunctionType, string toJunctionType, string argSourceType, int argIndex) { if (argIndex < 0 || argIndex > 65535) // 下标不合法 { return new { state = false }; } // 检查字面量是否可转换枚举类型 if (!EnumHelper.TryConvertEnum(argSourceType, out var tmpArgSourceType)) { return new { state = false }; } if (!EnumHelper.TryConvertEnum(fromJunctionType, out var tmpFromJunctionType)) { return new { state = false }; } if (!EnumHelper.TryConvertEnum(toJunctionType, out var tmpToJunctionType)) { return new { state = false }; } // 检查控制点类别,判断此次连接请求是否符合预期 if (tmpFromJunctionType == JunctionType.ArgData) { if (tmpToJunctionType == JunctionType.ReturnData) { (fromNodeGuid, toNodeGuid) = (toNodeGuid, fromNodeGuid);// 需要反转 } else { return new { state = false }; // 非预期的控制点连接 } } else if (tmpFromJunctionType == JunctionType.ReturnData) { if (tmpToJunctionType == JunctionType.ArgData) { // 顺序正确无须反转 } else { return new { state = false }; // 非预期的控制点连接 } } else // 其它类型的控制点,排除 { return new { state = false }; // 非预期的控制点连接 } // 调用环境接口进行连接 var result = await environment.ConnectArgSourceNodeAsync(fromNodeGuid, toNodeGuid, tmpFromJunctionType, tmpToJunctionType, tmpArgSourceType, argIndex); return new { state = result }; } /// /// 远程移除节点的参数传递关系 /// /// 起始节点Guid /// 目标节点Guid /// 目标节点的第几个参数 [AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveArgSourceConnect)] public async Task RemoveArgSourceConnect(string fromNodeGuid, string toNodeGuid, int argIndex) { var result = await environment.RemoveConnectArgSourceAsync(fromNodeGuid, toNodeGuid, argIndex); return new { state = result }; } /// /// 移动了某个节点(远程插件使用) /// /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.MoveNode)] public void MoveNode(string nodeGuid, double x, double y) { environment.MoveNode(nodeGuid, x, y); } /// /// 设置起点控件 /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.SetStartNode)] public async Task SetStartNode([NotNull]string nodeGuid) { return await environment.SetStartNodeAsync(nodeGuid); } #if false /// /// 中断指定节点,并指定中断等级。 /// /// 被中断的目标节点Guid /// 是否中断 /// 操作是否成功 [AutoSocketHandle(ThemeValue = EnvMsgTheme.SetNodeInterrupt)] public async Task SetNodeInterruptAsync(string nodeGuid, bool isInterrupt) { return false; // return await this.environment.SetNodeInterruptAsync(nodeGuid, isInterrupt); } /// /// 添加表达式中断 /// /// 如果是节点,传入Guid;如果是对象,传入类型FullName /// 合法的条件表达式 /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.AddInterruptExpression)] public async Task AddInterruptExpression(string key, string expression) { return await environment.AddInterruptExpressionAsync(key, expression); } /// /// 设置对象的监视状态 /// /// 如果是节点,传入Guid;如果是对象,传入类型FullName /// ture监视对象;false取消对象监视 /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.SetMonitor)] public void SetMonitorObjState(string key, bool isMonitor) { environment.SetMonitorObjState(key, isMonitor); } #endif /// /// 节点数据更改 /// /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.ValueNotification)] public async Task ValueNotification(string nodeGuid, string path, string value) { await environment.NotificationNodeValueChangeAsync(nodeGuid, path, value); } /// /// 增加/减少节点入参可选类型参数的个数 /// /// /// /// [AutoSocketHandle(ThemeValue = EnvMsgTheme.ChangeParameter)] public async Task ChangeParameter(string nodeGuid, bool isAdd, int paramIndex) { var result = await environment.ChangeParameter(nodeGuid, isAdd, paramIndex); return new { state = result }; } } }