PlcOpcUA.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using ProjectBase.Data.Logs;
  5. using ProjectBase.Data.Redis;
  6. using SIMDP.Model;
  7. using Opc.Ua;
  8. using OpcUaHelper;
  9. using Opc.Ua.Client.Controls;
  10. using Newtonsoft.Json.Linq;
  11. namespace SIMDP.Device
  12. {
  13. public class PlcOpcUA : AbstractBaseDevice
  14. {
  15. #region 数据定义
  16. protected OpcUaClient m_OpcUaClient;
  17. protected string Address = "";
  18. protected Dictionary<string, OpcDataPointInfo> allPoints = new Dictionary<string, OpcDataPointInfo>();
  19. protected List<OpcDataPointInfo> monitorPoints = new List<OpcDataPointInfo>();
  20. #endregion
  21. #region TYPE定义
  22. public enum VarType
  23. {
  24. Bit = 1,
  25. Byte = 2,
  26. Int = 3,
  27. Word = 4,
  28. DInt = 5,
  29. DWord = 6,
  30. Real = 7,
  31. LReal = 8,
  32. String = 9
  33. }
  34. public class OpcUaConfig
  35. {
  36. public OpcUaConfig(string json)
  37. {//"opc.tcp://DESKTOP-PA2AC31:53530/OPCUA/SimulationServer"
  38. JObject jObject = JObject.Parse(json);
  39. JToken token = jObject["Address"];
  40. if (token != null)
  41. Address = (string)token;
  42. token = jObject["Timer"];
  43. if (token != null)
  44. TIMER = Convert.ToDouble(token.ToString());
  45. }
  46. public string Address { get; set; }
  47. public double TIMER { get; set; } = 1000;
  48. }
  49. public class OpcDataPointInfo
  50. {
  51. // 节点配置信息
  52. public MoDataPoint mo;
  53. public string Tag { get; set; }//标签 例子:"ns=3;i=1008"
  54. public VarType TYPE { get; set; }
  55. public object value = null;
  56. public MethodInfo proc = null;
  57. public OpcDataPointInfo(MoDataPoint _mo)
  58. {
  59. mo = _mo;
  60. Tag = mo.DataPointSource;
  61. TYPE = getVarTypeByDataPointType(mo.DataPointType);
  62. }
  63. VarType getVarTypeByDataPointType(long type)
  64. {//常用的1、5、9 1bool 5double 9string
  65. if (type == 1)
  66. return VarType.Bit;
  67. else if (type == 2)
  68. return VarType.Byte;
  69. else if (type == 3)
  70. return VarType.Int;
  71. else if (type == 4)
  72. return VarType.Word;
  73. else if (type == 5)
  74. return VarType.DInt;
  75. else if (type == 6)
  76. return VarType.DWord;
  77. else if (type == 7)
  78. return VarType.Real;
  79. else if (type == 8)
  80. return VarType.LReal;
  81. else if (type == 9)
  82. return VarType.String;
  83. else
  84. return VarType.Bit;
  85. }
  86. }
  87. #endregion
  88. #region 接口实现
  89. public override void Start(MoPlcInfo _plcInfo, List<MoDataPoint> _dataPoints)
  90. {
  91. plcInfo = _plcInfo;
  92. OpcUaConfig plcConfig = new OpcUaConfig(plcInfo.LinkConfig);
  93. m_OpcUaClient = new OpcUaClient();
  94. m_OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken());
  95. Address = plcConfig.Address;
  96. timer.Interval = plcConfig.TIMER;
  97. timer.Elapsed += timer_Elapsed;
  98. timer.AutoReset = false;
  99. // PLC未连接状态
  100. SetRedisPlcDisConnect();
  101. // 创建PLC数据点表
  102. CreateDataPointList(_dataPoints);
  103. // 初始化自定义函数
  104. actionStart();
  105. // 启动时尝试连接一次设备
  106. Connect();
  107. // 启动定时器
  108. timerStopped = false;
  109. timer.Start();
  110. }
  111. public override void Stop()
  112. {
  113. actionStop();
  114. timerStopped = true;
  115. }
  116. public override bool isConnected()
  117. {
  118. return m_OpcUaClient.Connected;
  119. }
  120. protected override bool Connect()
  121. {
  122. try
  123. {
  124. m_OpcUaClient.ConnectServer(Address);
  125. }
  126. catch (Exception ex)
  127. {
  128. ClientUtils.HandleException("Connected Failed", ex);
  129. }
  130. if (m_OpcUaClient.Connected)
  131. {
  132. LogHelper.log.Info("已连接到OPC:" + m_OpcUaClient.OpcUaName);
  133. SetRedisPlcConnected();
  134. actionConnected();
  135. return true;
  136. }
  137. else
  138. {
  139. LogHelper.log.Warn("未能连接到OPC,状态:" + m_OpcUaClient.Connected.ToString());
  140. SetRedisPlcDisConnect();
  141. return false;
  142. }
  143. }
  144. protected override void Disconnect()
  145. {
  146. if (m_OpcUaClient != null)
  147. m_OpcUaClient.Disconnect();
  148. SetRedisPlcDisConnect();
  149. }
  150. void CreateDataPointList(List<MoDataPoint> dataPoints)
  151. {
  152. if (redis == null)
  153. redis = new RedisHelper();
  154. Type t = this.GetType();
  155. foreach (MoDataPoint dataPoint in dataPoints)
  156. {
  157. OpcDataPointInfo dataPointInfo = new OpcDataPointInfo(dataPoint);
  158. allPoints.Add(dataPoint.DataPointName, dataPointInfo);
  159. redis.SetString(dataPoint.DataPointId.ToString() + dataPoint.DataPointName, "");
  160. // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑
  161. if (dataPoint.DataProc.Trim() != "")
  162. {
  163. dataPointInfo.proc = t.GetMethod(dataPoint.DataProc);
  164. monitorPoints.Add(dataPointInfo);
  165. }
  166. }
  167. }
  168. #endregion
  169. #region 读写操作
  170. public bool Read(string dataPointName, out object value)
  171. {
  172. value = null;
  173. if (!allPoints.ContainsKey(dataPointName))
  174. {
  175. return false;
  176. }
  177. OpcDataPointInfo p = allPoints[dataPointName];
  178. return Read(p, out value);
  179. }
  180. public bool Read(OpcDataPointInfo p, out object value)
  181. {
  182. switch (p.TYPE)
  183. {
  184. case VarType.Bit:
  185. value = Convert.ToBoolean(m_OpcUaClient.ReadNode<bool>(p.Tag));
  186. break;
  187. case VarType.Byte:
  188. value = Convert.ToByte(m_OpcUaClient.ReadNode<byte>(p.Tag));
  189. break;
  190. case VarType.Int:
  191. value = Convert.ToInt16(m_OpcUaClient.ReadNode<short>(p.Tag));
  192. break;
  193. case VarType.Word:
  194. value = Convert.ToUInt16(m_OpcUaClient.ReadNode<ushort>(p.Tag));
  195. break;
  196. case VarType.DInt:
  197. value = Convert.ToInt32(m_OpcUaClient.ReadNode<int>(p.Tag));
  198. break;
  199. case VarType.DWord:
  200. value = Convert.ToUInt32(m_OpcUaClient.ReadNode<uint>(p.Tag));
  201. break;
  202. case VarType.Real:
  203. value = Convert.ToSingle(m_OpcUaClient.ReadNode<float>(p.Tag));
  204. break;
  205. case VarType.LReal:
  206. value = Convert.ToDouble(m_OpcUaClient.ReadNode<double>(p.Tag));
  207. break;
  208. case VarType.String:
  209. value = m_OpcUaClient.ReadNode<string>(p.Tag).ToString();
  210. break;
  211. default:
  212. value = null;
  213. return false;
  214. }
  215. UpdataRedisDataPoint(p.mo, value.ToString());
  216. return true;
  217. }
  218. public bool Write(string dataPointName, object value)
  219. {
  220. if (!allPoints.ContainsKey(dataPointName))
  221. {
  222. return false;
  223. }
  224. OpcDataPointInfo p = allPoints[dataPointName];
  225. switch (p.TYPE)
  226. {
  227. case VarType.Bit:
  228. m_OpcUaClient.WriteNode(p.Tag, Convert.ToBoolean(value));
  229. break;
  230. case VarType.Byte:
  231. m_OpcUaClient.WriteNode(p.Tag, Convert.ToByte(value));
  232. break;
  233. case VarType.Int:
  234. m_OpcUaClient.WriteNode(p.Tag, Convert.ToInt16(value));
  235. break;
  236. case VarType.Word:
  237. m_OpcUaClient.WriteNode(p.Tag, Convert.ToUInt16(value));
  238. break;
  239. case VarType.DInt:
  240. m_OpcUaClient.WriteNode(p.Tag, Convert.ToInt32(value));
  241. break;
  242. case VarType.DWord:
  243. m_OpcUaClient.WriteNode(p.Tag, Convert.ToUInt32(value));
  244. break;
  245. case VarType.Real:
  246. m_OpcUaClient.WriteNode(p.Tag, Convert.ToSingle(value));
  247. break;
  248. case VarType.LReal:
  249. m_OpcUaClient.WriteNode(p.Tag, Convert.ToDouble(value));
  250. break;
  251. case VarType.String:
  252. m_OpcUaClient.WriteNode(p.Tag, value.ToString());
  253. break;
  254. default:
  255. return false;
  256. }
  257. //LogHelper.log.Debug($"PLC信号({dataPointName})写入值:{value.ToString()}");
  258. UpdataRedisDataPoint(p.mo, value.ToString());
  259. return true;
  260. }
  261. #endregion
  262. }
  263. }