PlcS7Net.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. using System;
  2. using System.Collections.Generic;
  3. using S7.Net;
  4. using Newtonsoft.Json.Linq;
  5. using ProjectBase.Data.Logs;
  6. using ProjectBase.Data.Redis;
  7. using ProjectBase.Data.BaseDAL;
  8. using SIMDP.BLL;
  9. using SIMDP.Model;
  10. using ProjectBase.Util;
  11. using System.Timers;
  12. using System.Reflection;
  13. namespace SIMDP.Device
  14. {
  15. public class PlcS7Net : AbstractBaseDevice
  16. {
  17. #region 数据定义
  18. /// <summary>
  19. /// PLC对象
  20. /// </summary>
  21. protected Plc S7Plc;
  22. /// <summary>
  23. /// 数据节点字典 key-变量名称, value-节点信息
  24. /// </summary>
  25. protected Dictionary<string, S7NetDataPointInfo> allPoints = new Dictionary<string, S7NetDataPointInfo>();
  26. /// <summary>
  27. /// 监控节点列表
  28. /// </summary>
  29. protected List<S7NetDataPointInfo> monitorPoints = new List<S7NetDataPointInfo>();
  30. #endregion
  31. #region TYPE定义
  32. public class S7NetPlcConfig
  33. {
  34. public S7NetPlcConfig(string json)
  35. {
  36. JObject jObject = JObject.Parse(json);
  37. CPU = getCpuTypeByName((string)jObject["CPU"]);
  38. JToken token = jObject["IP"];
  39. if (token != null)
  40. IP = (string)token;
  41. token = jObject["Rack"];
  42. if (token != null)
  43. RACK = (short)token;
  44. token = jObject["Slot"];
  45. if (token != null)
  46. SLOT = (short)token;
  47. token = jObject["Timer"];
  48. if (token != null)
  49. TIMER = Convert.ToDouble(token.ToString());
  50. }
  51. public CpuType CPU { get; set; }
  52. public string IP { get; set; } = "192.168.0.1";
  53. public short RACK { get; set; } = 0;
  54. public short SLOT { get; set; } = 1;
  55. public double TIMER { get; set; } = 1000;
  56. CpuType getCpuTypeByName(string cpuName)
  57. {
  58. if (cpuName.Contains("1200"))
  59. return CpuType.S71200;
  60. else if (cpuName.Contains("1500"))
  61. return CpuType.S71500;
  62. else if (cpuName.Contains("200"))
  63. return CpuType.S7200;
  64. else if (cpuName.Contains("300"))
  65. return CpuType.S7300;
  66. else if (cpuName.Contains("400"))
  67. return CpuType.S7400;
  68. else
  69. return CpuType.S71500; // 默认为1500
  70. }
  71. }
  72. public class S7NetDataPointInfo
  73. {
  74. // 节点配置信息
  75. public MoDataPoint mo;
  76. // 节点属性
  77. public short DB { get; set; }
  78. public short ADDR { get; set; }
  79. public VarType TYPE { get; set; }
  80. public byte BIT { get; set; } = 0;
  81. // 节点值及动作定义
  82. public object value = null;
  83. public MethodInfo proc = null;
  84. public S7NetDataPointInfo(MoDataPoint _mo)
  85. {
  86. mo = _mo;
  87. JObject jObject = JObject.Parse(mo.DataPointSource);
  88. DB = Convert.ToInt16((string)jObject["DB"]);
  89. ADDR = Convert.ToInt16((string)jObject["ADDR"]);
  90. TYPE = getVarTypeByDataPointType(mo.DataPointType);
  91. JToken token = jObject["BIT"];
  92. if (token != null)
  93. BIT = Convert.ToByte(token.ToString());
  94. }
  95. VarType getVarTypeByDataPointType(long type)
  96. {
  97. if (type == 1)
  98. return VarType.Bit;
  99. else if (type == 2)
  100. return VarType.Byte;
  101. else if (type == 3)
  102. return VarType.Int;
  103. else if (type == 4)
  104. return VarType.Word;
  105. else if (type == 5)
  106. return VarType.DInt;
  107. else if (type == 6)
  108. return VarType.DWord;
  109. else if (type == 7)
  110. return VarType.Real;
  111. else if (type == 9)
  112. return VarType.String;
  113. else
  114. return VarType.Bit;
  115. }
  116. }
  117. #endregion
  118. #region 接口实现
  119. public override void Start(MoPlcInfo _plcInfo, List<MoDataPoint> _dataPoints)
  120. {
  121. plcInfo = _plcInfo;
  122. S7NetPlcConfig plcConfig = new S7NetPlcConfig(plcInfo.LinkConfig);
  123. S7Plc = new Plc(plcConfig.CPU, plcConfig.IP, plcConfig.RACK, plcConfig.SLOT);
  124. timer.Interval = plcConfig.TIMER;
  125. timer.Elapsed += timer_Elapsed;
  126. timer.AutoReset = false;
  127. // PLC未连接状态
  128. SetRedisPlcDisConnect();
  129. // 创建PLC数据点表
  130. CreateDataPointList(_dataPoints);
  131. // 初始化自定义函数
  132. actionStart();
  133. // 启动时尝试连接一次设备
  134. Connect();
  135. // 启动定时器
  136. timerStopped = false;
  137. timer.Start();
  138. }
  139. public override bool isConnected()
  140. {
  141. return S7Plc.IsConnected;
  142. }
  143. protected override bool Connect()
  144. {
  145. S7Plc.Open();
  146. SetRedisPlcConnected();
  147. LogHelper.log.Info("已连接到PLC:" + S7Plc.IP);
  148. return isConnected();
  149. }
  150. protected override void Disconnect()
  151. {
  152. if (S7Plc != null)
  153. S7Plc.Close();
  154. SetRedisPlcDisConnect();
  155. }
  156. void CreateDataPointList(List<MoDataPoint> dataPoints)
  157. {
  158. if (redis == null)
  159. redis = new RedisHelper();
  160. Type t = this.GetType();
  161. foreach (MoDataPoint dataPoint in dataPoints)
  162. {
  163. S7NetDataPointInfo dataPointInfo = new S7NetDataPointInfo(dataPoint);
  164. allPoints.Add(dataPoint.DataPointName, dataPointInfo);
  165. redis.SetString(dataPoint.DataPointId.ToString() + dataPoint.DataPointName, "");
  166. //if (BLLFactory<BlDataGroup>.Instance.IsSignalGroupById(dataPoint.DataPointGroupId))
  167. // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑
  168. if (dataPoint.DataProc.Trim() != "")
  169. {
  170. dataPointInfo.proc = t.GetMethod(dataPoint.DataProc);
  171. monitorPoints.Add(dataPointInfo);
  172. }
  173. }
  174. }
  175. #endregion
  176. #region 读写操作
  177. /// <summary>
  178. /// 读取节点数据
  179. /// </summary>
  180. public bool Read(string dataPointName, out object value)
  181. {
  182. value = null;
  183. if (!allPoints.ContainsKey(dataPointName))
  184. {
  185. return false;
  186. }
  187. S7NetDataPointInfo p = allPoints[dataPointName];
  188. return Read(p, out value);
  189. }
  190. public bool Read(S7NetDataPointInfo p, out object value)
  191. {
  192. switch (p.TYPE)
  193. {
  194. case VarType.Bit:
  195. value = Convert.ToBoolean(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1, p.BIT));
  196. break;
  197. case VarType.Byte:
  198. value = Convert.ToByte(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  199. break;
  200. case VarType.Int:
  201. value = Convert.ToInt16(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  202. break;
  203. case VarType.Word:
  204. value = Convert.ToUInt16(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  205. break;
  206. case VarType.DInt:
  207. value = Convert.ToInt32(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  208. break;
  209. case VarType.DWord:
  210. value = Convert.ToUInt32(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  211. break;
  212. case VarType.Real:
  213. value = Convert.ToDouble(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1));
  214. break;
  215. case VarType.String:
  216. byte length = (byte)S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR + 1, VarType.Byte, 1);
  217. value = S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR + 2, p.TYPE, length).ToString();
  218. break;
  219. default:
  220. value = null;
  221. return false;
  222. }
  223. UpdataRedisDataPoint(p.mo, value.ToString());
  224. return true;
  225. }
  226. /// <summary>
  227. /// 写入节点数据
  228. /// </summary>
  229. public bool Write(string dataPointName, object value)
  230. {
  231. if (!allPoints.ContainsKey(dataPointName))
  232. {
  233. return false;
  234. }
  235. S7NetDataPointInfo p = allPoints[dataPointName];
  236. switch (p.TYPE)
  237. {
  238. case VarType.Bit:
  239. S7Plc.WriteBit(DataType.DataBlock, p.DB, p.ADDR, p.BIT, Convert.ToBoolean(value));
  240. break;
  241. case VarType.Byte:
  242. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToByte(value));
  243. break;
  244. case VarType.Int:
  245. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToInt16(value));
  246. break;
  247. case VarType.Word:
  248. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToUInt16(value));
  249. break;
  250. case VarType.DInt:
  251. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToInt32(value));
  252. break;
  253. case VarType.DWord:
  254. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToUInt32(value));
  255. break;
  256. case VarType.Real:
  257. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToDouble(value));
  258. break;
  259. case VarType.String:
  260. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR + 1, Convert.ToByte(value.ToString().Length));
  261. S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR + 2, value.ToString());
  262. break;
  263. default:
  264. return false;
  265. }
  266. UpdataRedisDataPoint(p.mo, value.ToString());
  267. return true;
  268. }
  269. #endregion
  270. }
  271. }