/// <summary> /// 删除文件夹 /// </summary> /// <param name="motherPathName"></param> /// <returns></returns> public string DeleteFolder(string motherPathName) { string r = "无效操作"; try { string iniPath = System.AppDomain.CurrentDomain.BaseDirectory + "/HR_Models.ini"; Ini ini = new Ini(iniPath); string tempPath = ini.ReadValue("root", "UserRootPath") + PublicClassRule.JieXiMuLu(motherPathName);//解析目录 //已经有路径了,再查一下该文件夹是否正在使用中 bool isUsing = false; for (int i = 0; i < YingHeXinList.Count; i++) { if (YingHeXinList[i].CopyModel_To_TargetPath == tempPath) { isUsing = true; break; } } if (isUsing) { r = "该模型正在被使用,请停止试验后再试。"; } else { r = PublicClassTools.Delete(tempPath); } } catch (Exception) { r = "文件夹名称解析异常"; } return(r); }
//// <summary> /// 创建新的试验 /// 这里有几个关键步骤:创建管理连接、复制文件、启动文件、实现通讯 /// </summary> /// <param name="uid">用户编号</param> /// <param name="type">试验类型</param> /// <param name="hrID">华人设定的模板模型编号</param> /// <param name="look_uid">如果看其他人的试验,这里写别人的uid,默认不写为0</param> /// <param name="motherPathName">被查看的用户路径名称 eg.55_20191206144001New</param> /// <returns></returns> public ManagerMessage CreateNew_ShiYan(int uid, ShiYanCreateType type, int hrID, string m_Setting_Arguments, int look_uid = 0, string motherPathName = "") { // ManagerMessage r = new ManagerMessage(); r.ID = PublicClassRule.MakeMessageID(YingHeXinList, TCPConnectMax);//运算生成 r.UID = uid; r.CreateType = type; r.HR_Make_ID = hrID; r.Status = ShiYanStatus.New; r.Look_Other_UID = look_uid; r.SourceModelPath = motherPathName; r.M_Setting_Arguments = m_Setting_Arguments; #region 路径处理 try { PublicClassRule.Self_Make_Path(ref r, motherPathName);//根据创建类型,分配相关路径 } catch (Exception e) { Read_Exception(ref r, e); } #endregion YingHeXinList.Add(r); return(r); }
public string SetSendDataStr(string message, int id) { string r = "无效操作"; //首先验证数据是否符合规范:解析数量、查看是否都是数字,id是否存在 var rows = YingHeXinList.Where(o => o.ID == id).ToList(); if (rows.Count > 0) { //查到有ID string[] sArray = message.Split(','); //这是当前想要发的数据 string Sstrs = PublicClassRule.GetValues(rows[0].HR_Make_ID.ToString(), "tcpSendBytes"); //配置中要发送数据类型[这是正确的数据] string[] sRightArray = Sstrs.Split(','); if (sArray.Length == sRightArray.Length) { //与配置项相符,再验证数据是否与要求类型相符 try { byte[] sendByteDataList = PublicClassRule.MakeDataToBytes(rows[0].HR_Make_ID, message); if (sendByteDataList == null) { //无效 r = "数据无效"; } else { //可以记录,发送 rows[0].SendData = message; rows[0].Web_Heart++;//web心跳 r = "发送数据变更成功"; } } catch (Exception) { r = "数据转换不正确,可能有的数据超过类型限制。"; } } else { r = "Message字符结构不正确,请正确输入正确数量的数据。"; } } else { r = "ID无效"; } return(r); }
/// <summary> /// 读取配置文件,输入输出都是什么数据。 /// </summary> /// <param name="HR_id"></param> /// <param name="tcpReceiveSendBytesName">tcpReceiveBytes/tcpSendBytes</param> /// <returns></returns> public static int Read_Setting_Length(int HR_id, string tcpReceiveSendBytesName) { string Rstrs = PublicClassRule.GetValues(HR_id.ToString(), tcpReceiveSendBytesName);//接收数据类型 string[] rArray = Rstrs.Split(','); int rLength = rArray.Length; //rLength = GetTCP_Receive_Length(rArray, rLength);//这个方法用错了!!留着启示后人 2019年12月13日17:02:03 就不应该用 return(rLength); }
/// <summary> /// 制作要发送的字节 /// </summary> /// <param name="HR_Make_ID"></param> /// <param name="sendData"></param> /// <returns></returns> internal static byte[] MakeDataToBytes(int HR_Make_ID, string sendData) { byte[] realByteOut = null; string Sstrs = PublicClassRule.GetValues(HR_Make_ID.ToString(), "tcpSendBytes"); //要发送数据类型 string[] sArray = Sstrs.Split(','); //这是数据类型数组 string[] dataArray = sendData.Split(','); //这是要发送的数据数组 List <byte[]> outBytesList = new List <byte[]>(); //这里最后要发送出去的byte[]组 //标注是否翻转,true不翻转 false翻转 bool isTCP_IEC = IsTCP_IEC(HR_Make_ID); if (sArray.Length == dataArray.Length) { //数据数量相同 #region 制作byte for (int i = 0; i < dataArray.Length; i++) { byte[] temp = MakeOneBytes(sArray[i], dataArray[i], isTCP_IEC); if (temp != null) { outBytesList.Add(temp); } else { } } //制作结束,封装开始。 realByteOut = PublicClassTools.MergeBytes(outBytesList); #endregion } else { //数据数量不同,不执行发送指令 } return(realByteOut); }
/// <summary> /// 直接向文件夹中传文件 /// </summary> /// <param name="motherPathName"></param> /// <param name="data"></param> /// <param name="fileName"></param> /// <returns></returns> //public string UpLoad_Mfile(string motherPathName, byte[] data, string fileName) //{ // string r = "无效操作"; // string iniPath = System.AppDomain.CurrentDomain.BaseDirectory + "/HR_Models.ini"; // Ini ini = new Ini(iniPath); // string tempPath = ini.ReadValue("root", "UserRootPath") + PublicClassRule.JieXiMuLu(motherPathName);//解析目录 // string path = string.Format(@"{0}\{1}", tempPath/*,DateTime.Now.ToString("yyyyMMddHHmmss")*/, fileName); // bool r2 = FileHelper.ByteToFile(data, path); // if (r2) // { // r = "上传成功"; // } // else // { // r = "上传失败"; // } // return r; //} /// <summary> /// 下载文件 /// </summary> /// <param name="motherPathName"></param> /// <param name="fileName"></param> /// <returns></returns> public byte[] DownLoad_Mfile(string motherPathName, string fileName) { string r = "无效操作"; try { string iniPath = System.AppDomain.CurrentDomain.BaseDirectory + "/HR_Models.ini"; Ini ini = new Ini(iniPath); string tempPath = ini.ReadValue("root", "UserRootPath") + PublicClassRule.JieXiMuLu(motherPathName);//解析目录 //已经有路径了,再查一下该文件夹是否正在使用中 //拼接文件完整路径 string fullfilename = string.Format("{0}{1}", tempPath, fileName); return(FileHelper.FileToByte(fullfilename)); } catch (Exception) { r = "文件夹名称解析异常"; } return(null); }
/// <summary> /// 启动simlink的过程 /// </summary> /// <param name="row"></param> /// <returns></returns> private async Task MakeSimlinkRun(ManagerMessage row) { await Task.Run(() => { //要运行的路径是row.CopyModel_To_TargetPath //文件夹里面的命令需要复制过来、你看看怎么能启动起来 #region 将来不会用这里的代码 2019年12月9日09:40:17 //System.Diagnostics.Process cmd_MakeRun = new System.Diagnostics.Process(); //cmd_MakeRun.StartInfo.FileName = @"D:\uuu\UID44\44_20191209114531New\MGtcp\hello.bat"; ////cmd_MakeRun.StartInfo.UserName = "******"; //cmd_MakeRun.StartInfo.UseShellExecute = false; //cmd_MakeRun.Start(); //row.PID = CMDClass.FindPID("MATLAB R2018a", @"C:\Program Files\MATLAB\R2018a\bin\win64\MATLAB.exe"); ////row.PID = cmd_MakeRun.Id;//把程序启动起来的PID记录下来 ////cmd_MakeRun.Kill(); //CMDClass.KillProcess("QQ", cmd_MakeRun.StartInfo.FileName);//两种方式都能把!QQ干掉!! ////CMDClass.KillProcess(row.PID); #endregion string arguments = PublicClassRule.GetValues(row.HR_Make_ID.ToString(), "arguments"); //原始参数 arguments = PublicClassRule.MakeArguments(arguments, row.HR_Make_ID, row.CopyModel_To_TargetPath); //结构化之后的最终使用参数 //修改M文件中的 input 的ID 本段属于文件操作,修改.m文件内容 string m_path = string.Format("{0}{1}", row.CopyModel_To_TargetPath, PublicClassRule.GetValues(row.HR_Make_ID.ToString(), "mFileName")); PublicClassRule.Edit_M_File(m_path, row.HR_Make_ID, row.ID, row.M_Setting_Arguments); MakeRun(arguments, ref row); //等待程序和服务TCP通讯,!!!注意,此时,这个进程不会停止,不会自动关闭。只能等待kill PID 2019年12月9日14:40:17 }); }
/// <summary> /// 数据解析:从byte[]到数据 /// </summary> /// <param name="recvDataBuffer"></param> /// <param name="HR_Make_ID"></param> /// <returns></returns> internal static List <double> MakebytesToData(byte[] recvDataBuffer, int HR_Make_ID) { List <double> r = new List <double>(); //int length = PublicClassTools.Read_Setting_Length(HR_Make_ID, "tcpReceiveBytes");//计算长度 string Rstrs = PublicClassRule.GetValues(HR_Make_ID.ToString(), "tcpReceiveBytes");//接收数据类型 string[] rArray = Rstrs.Split(','); int startIndex = 0; for (int i = 0; i < rArray.Length; i++) { //做数据 r.Add(MakeOneData(rArray[i], startIndex, recvDataBuffer)); //重置位置 startIndex = startIndex + PublicClassTools.GetTypeByteLength(rArray[i].Trim()); } return(r); }
/// <summary> /// 处理接收来的TCP通讯数据,获取ID /// </summary> /// <param name="e"></param> /// <returns>返回的ID是 管理试验的ID,注意!不是索引</returns> private int MakeDataTCP(NetEventArgs e) { int ID = -1; //默认不知道对应我们的 哪行数据ID,先查一下SESSION,看看有没有。有就可以直接用了。 //没有进行对比ID操作,进行匹配,数据长度也能获取到,依据配置文件 //如果还是没有,就中断此链接 System.Net.EndPoint remote = e.Client.ClientSocket.RemoteEndPoint; bool canFindEndPoint = false; for (int i = 0; i < YingHeXinList.Count; i++) { if (string.Format("{0}:{1}", YingHeXinList[i].Remote_IP == null ? "0.0.0.0" : YingHeXinList[i].Remote_IP, YingHeXinList[i].Remote_Port) == remote.ToString()) { //找到了 canFindEndPoint = true; ID = YingHeXinList[i].ID; break; } } if (canFindEndPoint) { //找到了 } else { //没找到 //int id = e.Client.RecvDataBuffer[0];//通讯协议规定,第一个字节就是程序发出的ID指令。这个ID对应管理服务的0-200个可复用试验接口台。【注意,不是索引!】 int id = Convert.ToInt32(PublicClassRule.MakeOneData("double", 0, e.Client.RecvDataBuffer)); bool canFindID = false; for (int i = 0; i < YingHeXinList.Count; i++) { if (YingHeXinList[i].ID == id) { //找到了,EndPoint绑定进去 canFindID = true; //YingHeXinList[i].RemoteEndPoint = remote;//不知道为什么,此行注释的不行,程序中可以,但到了wcf,客户端收不到。 YingHeXinList[i].Remote_IP = ((System.Net.IPEndPoint)remote).Address.ToString(); YingHeXinList[i].Remote_Port = ((System.Net.IPEndPoint)remote).Port; YingHeXinList[i].TCP_OK_Start = DateTime.Now; ID = YingHeXinList[i].ID; YingHeXinList[i].Status = ShiYanStatus.Running; YingHeXinList[i].Tcp_TimeOut_Test = new TimeOutPlay(); YingHeXinList[i].Web_TimeOut_Test = new TimeOutPlay(); break; } } if (canFindID) { //找到了,数据绑定进去,哦上面EndPoint已经写入了 } else { //没找到,关闭此链接 e.Client.Close(); } } return(ID); }
private void RecvData(object sender, NetEventArgs e) { #region 接收数据应对措施 int id = MakeDataTCP(e);//查询ID if (id == -1) { //不处理 //【注意】程序中写了。如果返回值是-1说明没查到,此链接会被关闭。所以要处理不等于-1的即可 } else { //处理收到的数据 var row = YingHeXinList.Where(o => o.ID == id).ToList(); TimeSpan ts = DateTime.Now - row[0].TCP_OK_Start; row[0].TCP_GoOn_Time = string.Format("{0}天{1}小时{2}分{3}秒 {4}", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); //int length = PublicClassTools.Read_Setting_Length(row[0].HR_Make_ID, "tcpReceiveBytes"); //根据这个长度处理数据 List <double> receiveDataList = PublicClassRule.MakebytesToData(e.Client.RecvDataBuffer, row[0].HR_Make_ID); //把数据放置在对应的位置上 string rDataStr = ""; for (int i = 0; i < receiveDataList.Count; i++) { rDataStr = string.Format("{0},{1}", rDataStr, receiveDataList[i]); } //循环结束,最前方都会去掉 if (rDataStr.StartsWith(",")) { rDataStr = rDataStr.Substring(1); } row[0].ReceivedData = rDataStr; row[0].ReceivedTotalCount++; #region //补充:为了单一模型 MakeSingleData(true, id, rDataStr, row[0].TCP_GoOn_Time); #endregion //下面该回数据了,有来不往非君子。 //首先验证一下要发送的数据 2019年12月10日11:42:46 int slength = PublicClassTools.Read_Setting_Length(row[0].HR_Make_ID, "tcpSendBytesNames");//协议中要发送的数据长度 if (row[0].SendData == null) { //如果是空,给一个初始值 MakeSendDataStr(row, slength); } //再验证一下,这个数据的数量是不是正确 string[] sCount = row[0].SendData.Split(','); if (sCount.Length != slength) { //长度不正确 MakeSendDataStr(row, slength); } else { //长度正确 } //现在有要发送的数据了。开始制作byte[] byte[] sendByteDataList = PublicClassRule.MakeDataToBytes(row[0].HR_Make_ID, row[0].SendData); if (sendByteDataList == null) { //没数据可发 } else { //发送数据异常 SendData111(sendByteDataList, e.Client); row[0].SendTotalCount++; if (row[0].CreateType == ShiYanCreateType.New || true) //先不管了,不管怎么用,都记录吧 { //新建的试验记录日志 PublicClassRule.MakeLog(row[0]);//写tcp通讯的命令和返回值日志 } else { //复盘自己和别人的试验,不做日志记录 } } } /// <summary> /// 发送数据 /// </summary> /// <param name="_data"></param> /// <param name="sessionClient"></param> void SendData111(byte[] _data, Session sessionClient) { svr.Send(sessionClient, _data); string byteStr = ""; for (int i = 0; i < _data.Length; i++) { byteStr = byteStr + " " + _data[i].ToString("X2"); } string info = string.Format("发送数据:\tOmegaS Send data:\t{0} \tTo:{1}.", byteStr, sessionClient); Console.WriteLine(info); Console.Write(">"); } #endregion }
/// <summary> /// 启动simlink模型 /// </summary> /// <param name="arguments">启动参数,这是启动MATLAB的名称参数,在配置文件的属性中可以看到DEMO</param> /// <param name="row">PID记录在这里</param> private void MakeRun(string arguments, ref ManagerMessage row) { try { //string arguments = @"-nosplash -nodesktop -sd D:\MyWorkGGTest\one\MGtcp -r test"; System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(PublicClassRule.GetValues("root", "MATLAB_Process_FullPath"), arguments); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; System.Diagnostics.Process myprocess = new System.Diagnostics.Process(); myprocess.StartInfo = startInfo; myprocess.StartInfo.UseShellExecute = false; myprocess.StartInfo.CreateNoWindow = true; myprocess.StartInfo.RedirectStandardOutput = true; myprocess.Start(); row.PID = myprocess.Id; //获取PID myprocess.WaitForExit(); //进程会一直处于等待退出状态。 } catch (Exception ex) { } }
/// <summary> /// 逻辑流程:这里控制我们整个试验系统的状态 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Timer_LiuCheng_Elapsed(object sender, ElapsedEventArgs e) { for (int i = 0; i < YingHeXinList.Count; i++) { bool ThisTimeChanged = false;//本次循环有变化。有变化时跳出循环,等待下一次循环再做处理。 //因为有可能使用remove操作,这里去掉一行,后续可能导致顺序异常 switch (YingHeXinList[i].Status) { case ShiYanStatus.New: { #region 是新创建的,开始拷贝 YingHeXinList[i].Status = ShiYanStatus.FilesCopying; if (YingHeXinList[i].CreateType != ShiYanCreateType.ReView) { _ = Copy(YingHeXinList[i]); //【使用丢弃】不知道啥意思,反正这里我用异步操作了。2019年12月6日14:01:41 } else { //看自己的试验复盘,不需要复制。直接跳到复制完成。 YingHeXinList[i].Status = ShiYanStatus.FilesCopyCompleted; } #endregion } break; case ShiYanStatus.FilesCopying: { //这里不管,等待拷贝完成 } break; case ShiYanStatus.FilesCopyCompleted: { #region 已经拷贝好了,开始执行运行命令 YingHeXinList[i].Status = ShiYanStatus.CmdCommand; // TODO:这里将来要做重要操作,启动MATLAB的仿真程序,并且把仿真程序的ID记录下来。 _ = MakeSimlinkRun(YingHeXinList[i]); #endregion } break; case ShiYanStatus.CmdCommand: { //无需操作,等待通讯开始 } break; case ShiYanStatus.Running: { #region 正常运行的试验要查看通讯是否超时。包含simlink通讯超时和 web端通讯超时 PublicClassRule.CheckTimeOut(YingHeXinList[i]); #endregion } break; case ShiYanStatus.Error: case ShiYanStatus.Error_NoFind_FuPanPath: case ShiYanStatus.Error_NoFind_SourcePath: case ShiYanStatus.Error_No_MotherPath: case ShiYanStatus.Error_No_THIS_HR_ID: case ShiYanStatus.Error_UID_NOT_Equal_LookOtherUID: case ShiYanStatus.Error_Write_MotherPathName: { #region 错误状态的试验自动结束 YingHeXinList[i].Status = ShiYanStatus.End; #endregion } break; case ShiYanStatus.End: { #region MyRegion CMDClass.KillProcess(YingHeXinList[i].PID); //此处注意,可能要改为sleep或多线程。 MakeSingleData(false, YingHeXinList[i].ID, "", "t0"); YingHeXinList.RemoveAt(i); ThisTimeChanged = true; #endregion } break; default: break; } if (ThisTimeChanged) { break; } } }
/// <summary> /// 此方法提供单个试验配置的协议,提供给网站使用,便于动态创建页面 /// </summary> /// <param name="hrID"></param> /// <param name="xieyi"></param> /// <returns></returns> public string GetTag_By_HRID_And_XIEYI(int hrID, ShiYanXieYi xieyi) { return(PublicClassRule.GetValues(hrID.ToString(), xieyi.ToString()));//读取配置文件 }