|
@@ -25,18 +25,23 @@ using YG.Device;
|
|
|
using static SinumerikOpcUaAPI.Server;
|
|
|
using System.Collections;
|
|
|
using System.Runtime.Remoting.Messaging;
|
|
|
+using System.Reflection.Emit;
|
|
|
+using System.Runtime.Remoting.Channels;
|
|
|
|
|
|
namespace IMCS
|
|
|
{
|
|
|
public partial class Form_Main : Form
|
|
|
{
|
|
|
//public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/Work Pieces/";
|
|
|
- public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/NCExtend/wks.dir/nc_program/";
|
|
|
+ public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/NCExtend/wks.dir/";
|
|
|
//public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/Work Pieces/WORK_NC/";
|
|
|
public string CHANNEL_NO = "1";
|
|
|
public string TEMP_NC_NAME = "7999.MPF";
|
|
|
private uint currentToolArea = 1;
|
|
|
private ushort mNAMESPACE_INDEX = 2;
|
|
|
+
|
|
|
+ // 作为长连接进行bean的存储, key使用ip,
|
|
|
+ Dictionary<string, Server> opcServerMap = new Dictionary<string, Server>();
|
|
|
Server opcServer = null;
|
|
|
public Dictionary<string, Server> deviceList { get; set; } = new Dictionary<string, Server>();
|
|
|
|
|
@@ -90,6 +95,7 @@ namespace IMCS
|
|
|
{
|
|
|
if (!request.Url.ToString().Contains("favicon"))
|
|
|
{
|
|
|
+ RequestBody opcBody = null;
|
|
|
try
|
|
|
{
|
|
|
Stream stream = context.Request.InputStream;
|
|
@@ -99,7 +105,7 @@ namespace IMCS
|
|
|
YG.Log.Instance.WriteLogAdd(">>>===收到POST数据 : >>>>===" + body);
|
|
|
ResponseBody responseBody = new ResponseBody();
|
|
|
|
|
|
- RequestBody opcBody = JsonConvert.DeserializeObject<RequestBody>(body);
|
|
|
+ opcBody = JsonConvert.DeserializeObject<RequestBody>(body);
|
|
|
|
|
|
AddList(DateTime.Now.ToString(), "POST", opcBody.ServerUrl + opcBody.Type, "OK");
|
|
|
|
|
@@ -119,13 +125,29 @@ namespace IMCS
|
|
|
{
|
|
|
opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
|
|
|
}*/
|
|
|
- opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
|
|
|
+
|
|
|
+ // 从map中取出opcServer 判断是否存在,以及是否可用
|
|
|
+ opcServerMap.TryGetValue(opcBody.ServerUrl, out opcServer);
|
|
|
+
|
|
|
+ // 如果key不存在,或者存在单连接不上,则需要重新创建连接
|
|
|
+ if (!opcServerMap.ContainsKey(opcBody.ServerUrl) || !opcServer.Session.Connected)
|
|
|
+ {
|
|
|
+ opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
|
|
|
+
|
|
|
+ if (opcServer != null && opcServer.Session != null && opcServer.Session.Connected) {
|
|
|
+ // 存储Server bean
|
|
|
+ opcServerMap.Add(opcBody.ServerUrl, opcServer);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ //opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
|
|
|
+ //opcServer.IsOn
|
|
|
//else
|
|
|
//{
|
|
|
// opcServer.Session.Reconnect();
|
|
|
//}
|
|
|
|
|
|
- if (opcServer.Session.Connected)
|
|
|
+ if (opcServer.Session!=null && opcServer.Session.Connected)
|
|
|
{
|
|
|
if (opcBody.Type == ActionTypeEnum.Connect.ToString()) //连接状态
|
|
|
{
|
|
@@ -137,16 +159,11 @@ namespace IMCS
|
|
|
|
|
|
//responseBody.runDatasInfo = JsonConvert.SerializeObject(s7.deviceInfo);
|
|
|
|
|
|
- //string s = responseBody.runDatasInfo;
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/GeometricAxis/actFeedRate"); //进给倍率
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/speedOvr");//主轴倍率
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/actSpeed");//主轴实际速度
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/driveLoad");//主轴负载
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/ProgramInfo/selectedWorkPProg");//主程序
|
|
|
- opcBody.Addresses.Add("ns=2;s=/Channel/State/progStatus");//主程序
|
|
|
- //opcBody.Addresses.Add("ns=2;s=/Bag/State/opMode");//主程序
|
|
|
+ // 封装需要采集字段的数据
|
|
|
+ this.addAddress(opcBody);
|
|
|
List<string> values = opcServer.ReadValues(opcBody.Addresses);
|
|
|
- RunDatasInfo runDatasInfo = new RunDatasInfo();
|
|
|
+ responseBody.values = values;
|
|
|
+ /*RunDatasInfo runDatasInfo = new RunDatasInfo();
|
|
|
for (int i = 0; i < values.Count; i++)
|
|
|
{
|
|
|
if (i == 0)
|
|
@@ -174,9 +191,9 @@ namespace IMCS
|
|
|
runDatasInfo.content = values[i];
|
|
|
}
|
|
|
}
|
|
|
- responseBody.runDatasInfo = JsonConvert.SerializeObject(runDatasInfo);
|
|
|
+ responseBody.runDatasInfo = JsonConvert.SerializeObject(runDatasInfo);*/
|
|
|
|
|
|
- //报警
|
|
|
+ /*//报警
|
|
|
SinumerikOpcUaAPI.FilterDefinition m_filter = new SinumerikOpcUaAPI.FilterDefinition();
|
|
|
m_filter.AreaId = new NodeId("Sinumerik", (ushort)2);
|
|
|
m_filter.Severity = EventSeverity.Min;
|
|
@@ -189,7 +206,7 @@ namespace IMCS
|
|
|
for (int index = 0; index < m_filter.SelectClauses.Count<SimpleAttributeOperand>(); ++index)
|
|
|
{
|
|
|
responseBody.errorsInfo += m_filter.SelectClauses[index].ToString() + (object)index + " ";
|
|
|
- }
|
|
|
+ }*/
|
|
|
}
|
|
|
else if (opcBody.Type == ActionTypeEnum.ToolList.ToString())
|
|
|
{
|
|
@@ -200,7 +217,7 @@ namespace IMCS
|
|
|
);
|
|
|
int num = int.Parse(nums[0]);
|
|
|
List<ToolsInfo> toolInfoList = new List<ToolsInfo>();
|
|
|
- for(int index = 1; index <= num; index++)
|
|
|
+ for (int index = 1; index <= num; index++)
|
|
|
{
|
|
|
List<string> stringList = this.readVariables(opcServer, new string[10]
|
|
|
{
|
|
@@ -318,7 +335,7 @@ namespace IMCS
|
|
|
if (string.IsNullOrWhiteSpace(extension))
|
|
|
{
|
|
|
responseBody.result = false;
|
|
|
- responseBody.msg = file+"==文件名不合法";
|
|
|
+ responseBody.msg = file + "==文件名不合法";
|
|
|
break;
|
|
|
}
|
|
|
try
|
|
@@ -359,8 +376,9 @@ namespace IMCS
|
|
|
}
|
|
|
}
|
|
|
//设为主程序
|
|
|
- status = opcServer.MethodCallSelectProgram(UPLOAD_NC_PATH+opcBody.prgName, Convert.ToUInt32(CHANNEL_NO)).status;
|
|
|
- if (status != "Good"){
|
|
|
+ status = opcServer.MethodCallSelectProgram(UPLOAD_NC_PATH + opcBody.prgName, Convert.ToUInt32(CHANNEL_NO)).status;
|
|
|
+ if (status != "Good")
|
|
|
+ {
|
|
|
responseBody.msg = "选择失败";
|
|
|
responseBody.result = false;
|
|
|
}
|
|
@@ -387,7 +405,7 @@ namespace IMCS
|
|
|
//
|
|
|
|
|
|
byte[] op = opcServer.ReadFile(serverPath);
|
|
|
-
|
|
|
+
|
|
|
DiagnosticInfoCollection diagnosticInfos = null;
|
|
|
CallMethodRequestCollection callMethodRequestCollection = new CallMethodRequestCollection();
|
|
|
CallMethodResultCollection results = new CallMethodResultCollection();
|
|
@@ -400,13 +418,13 @@ namespace IMCS
|
|
|
RequestHeader requestHeader = new RequestHeader();
|
|
|
ResponseHeader responseHeader = opcServer.Session.Call(null, callMethodRequestCollection, out results, out diagnosticInfos);
|
|
|
Server.MethodCallResult methodCallResult = new MethodCallResult(results);
|
|
|
-
|
|
|
+
|
|
|
if (methodCallResult.status.ToUpper().Equals("GOOD"))
|
|
|
{
|
|
|
responseBody.msg = "上传文件成功";
|
|
|
YG.Log.Instance.WriteLogAdd(file + "上传文件成功");
|
|
|
Variant result3 = methodCallResult.results;
|
|
|
-
|
|
|
+
|
|
|
byte[] buff;
|
|
|
using (MemoryStream ms = new MemoryStream())
|
|
|
{
|
|
@@ -423,7 +441,7 @@ namespace IMCS
|
|
|
|
|
|
// 去除字符串中的空格
|
|
|
//string trimmedContent = fileContent.Trim(); // 使用Trim去除字符串首尾的空格
|
|
|
- // 或者使用Replace去除所有空格
|
|
|
+ // 或者使用Replace去除所有空格
|
|
|
string trimmedContent = fileContent.Replace(" ", "");
|
|
|
|
|
|
// 将处理过的字符串写回文件
|
|
@@ -431,8 +449,8 @@ namespace IMCS
|
|
|
|
|
|
|
|
|
string aa = result3.ToString();
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
}
|
|
@@ -476,7 +494,7 @@ namespace IMCS
|
|
|
//byte[] data = opcServer.ReadFile(file);
|
|
|
|
|
|
serverPath = UPLOAD_NC_PATH + Path.GetFileName(file);
|
|
|
- Server.MethodCallResult methodCallResult = opcServer.MethodCallDeleteFile( serverPath);
|
|
|
+ Server.MethodCallResult methodCallResult = opcServer.MethodCallDeleteFile(serverPath);
|
|
|
|
|
|
|
|
|
|
|
@@ -499,7 +517,7 @@ namespace IMCS
|
|
|
YG.Log.Instance.WriteLogAdd($"{ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
@@ -529,7 +547,7 @@ namespace IMCS
|
|
|
responseBody.msg = "同步文件失败===>" + ex.Message;
|
|
|
YG.Log.Instance.WriteLogAdd($"{ex.Message}");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -538,7 +556,8 @@ namespace IMCS
|
|
|
responseBody.msg = "服务器离线,连不上opcUa";
|
|
|
responseBody.result = false;
|
|
|
}
|
|
|
- opcServer.Disconnect();
|
|
|
+ YG.Log.Instance.WriteLogAdd("Disconnect!");
|
|
|
+
|
|
|
response.ContentType = "application/json;charset=UTF-8";
|
|
|
response.ContentEncoding = Encoding.UTF8;
|
|
|
response.AppendHeader("Content-Type", "application/json;charset=UTF-8");
|
|
@@ -557,6 +576,11 @@ namespace IMCS
|
|
|
}
|
|
|
catch (Exception opcex)
|
|
|
{
|
|
|
+ // 删除map中对应的bean
|
|
|
+ opcServerMap.Remove(opcBody.ServerUrl);
|
|
|
+ // 断开连接
|
|
|
+ opcServer.Disconnect();
|
|
|
+
|
|
|
AddList(DateTime.Now.ToString(), "POST", request.Url.ToString(), opcex.Message);
|
|
|
}
|
|
|
}
|
|
@@ -588,6 +612,119 @@ namespace IMCS
|
|
|
}
|
|
|
return server.ReadValues(nodeIdStrings);
|
|
|
}
|
|
|
+
|
|
|
+ private void addAddress(RequestBody opcBody)
|
|
|
+ {
|
|
|
+
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX310.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX311.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX311.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX311.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX312.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX312.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX313.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX314.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX314.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX314.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX316.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX326.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX326.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX326.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX326.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX491.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX493.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX493.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX495.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX497.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX497.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX499.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX501.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX501.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.5");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.6");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX554.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.5");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.6");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX555.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.6");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX556.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX557.5");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX558.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX558.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX559.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX559.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX559.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX559.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX560.5");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX570.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.4");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.5");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.6");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX574.7");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX575.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX575.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX578.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX578.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX578.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX579.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX579.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX579.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX579.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX590.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX590.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX590.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX624.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX624.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX626.0");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX626.1");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX626.2");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX626.3");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Plc/DB2.DBX626.4");
|
|
|
+
|
|
|
+
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Nck/SequencedAlarms/timeBCD");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Nck/SequencedAlarms/textIndex");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/GeometricAxis/feedRateOvr");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/speedOvr");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/actSpeed");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/MachineAxis/vaLoad");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Nck/ChannelDiagnose/setupTime");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/ChannelDiagnose/operatingTime");
|
|
|
+ opcBody.Addresses.Add("ns=2;s=/Channel/ProgramInfo/selectedWorkPProg");
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public class DeviceInfo
|
|
|
{
|
|
|
public string ConnectMsg
|