IoHeater.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. using Aitex.Core.Common.DeviceData;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.IOCore;
  5. using Aitex.Core.RT.OperationCenter;
  6. using Aitex.Core.RT.SCCore;
  7. using Aitex.Core.Util;
  8. using MECF.Framework.Common.CommonData;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Xml;
  13. namespace Aitex.Core.RT.Device.Unit
  14. {
  15. public class IoHeater : BaseDevice, IDevice
  16. {
  17. public double SetPointLimit
  18. {
  19. get
  20. {
  21. if (_aoSetPointLimit != null)
  22. return _isFloatAioType ? _aoSetPointLimit.FloatValue : _aoSetPointLimit.Value;
  23. if (_scRange != null)
  24. return _scRange.DoubleValue;
  25. return 100;
  26. }
  27. set
  28. {
  29. if (_aoSetPointLimit != null)
  30. {
  31. if (_isFloatAioType)
  32. _aoSetPointLimit.FloatValue = (float)value;
  33. else
  34. {
  35. _aoSetPointLimit.Value = (short)value;
  36. }
  37. }
  38. }
  39. }
  40. [Subscription(AITHeaterPropertyName.MonitorTcFeedback)]
  41. public float MonitorTcFeedback
  42. {
  43. get
  44. {
  45. if (_aiMonitorTcFeedback == null)
  46. return 0;
  47. float value = _isFloatAioType ? _aiMonitorTcFeedback.FloatValue : _aiMonitorTcFeedback.Value;
  48. float calibrated = CalibrationData(value, false);
  49. if (calibrated < 0)
  50. calibrated = 0;
  51. return calibrated;
  52. }
  53. }
  54. [Subscription(AITHeaterPropertyName.ControlTcFeedback)]
  55. public float ControlTcFeedback
  56. {
  57. get
  58. {
  59. if (_aiControlTcFeedback == null)
  60. return 0;
  61. float value = _isFloatAioType ? _aiControlTcFeedback.FloatValue : _aiControlTcFeedback.Value;
  62. float calibrated = CalibrationData(value, false);
  63. if (calibrated < 0)
  64. calibrated = 0;
  65. return calibrated;
  66. }
  67. }
  68. [Subscription(AITHeaterPropertyName.ControlTcSetPoint)]
  69. public float ControlTcSetPoint
  70. {
  71. get
  72. {
  73. if (_aoSetPoint == null)
  74. return 0;
  75. float value = _isFloatAioType ? _aoSetPoint.FloatValue : _aoSetPoint.Value;
  76. float calibrated = CalibrationData(value, false);
  77. if (calibrated < 0)
  78. calibrated = 0;
  79. return calibrated;
  80. }
  81. set
  82. {
  83. if (_aoSetPoint != null)
  84. {
  85. float calibrated = CalibrationData(value, true);
  86. if (calibrated < 0)
  87. calibrated = 0;
  88. if (_isFloatAioType)
  89. _aoSetPoint.FloatValue = (float)calibrated;
  90. else
  91. {
  92. _aoSetPoint.Value = (short)calibrated;
  93. }
  94. }
  95. }
  96. }
  97. [Subscription(AITHeaterPropertyName.IsMonitorTcBroken)]
  98. public bool IsMonitorTcBroken
  99. {
  100. get
  101. {
  102. if (_diMonitorTcBroken != null)
  103. return _diMonitorTcBroken.Value;
  104. return false;
  105. }
  106. }
  107. [Subscription(AITHeaterPropertyName.IsControlTcBroken)]
  108. public bool IsControlTcBroken
  109. {
  110. get
  111. {
  112. if (_diControlTcBroken != null)
  113. return _diControlTcBroken.Value;
  114. return false;
  115. }
  116. }
  117. [Subscription(AITHeaterPropertyName.IsPowerOnFeedback)]
  118. public bool IsPowerOnFeedback
  119. {
  120. get
  121. {
  122. if (_diPowerOnFeedback != null)
  123. return _diPowerOnFeedback.Value;
  124. if (_doPowerOn != null)
  125. return _doPowerOn.Value;
  126. return false;
  127. }
  128. }
  129. [Subscription(AITHeaterPropertyName.IsPowerOnSetPoint)]
  130. public bool IsPowerOnSetPoint
  131. {
  132. get
  133. {
  134. if (_doPowerOn != null)
  135. return _doPowerOn.Value;
  136. return false;
  137. }
  138. }
  139. public string Unit
  140. {
  141. get; set;
  142. }
  143. public AITHeaterData DeviceData
  144. {
  145. get
  146. {
  147. AITHeaterData data = new AITHeaterData()
  148. {
  149. Module = Module,
  150. DeviceName = Name,
  151. DeviceSchematicId = DeviceID,
  152. DisplayName = Display,
  153. FeedBack = ControlTcFeedback,
  154. MonitorTcFeedBack = MonitorTcFeedback,
  155. Scale = SetPointLimit,
  156. SetPoint = ControlTcSetPoint,
  157. IsPowerOn = IsPowerOnFeedback,
  158. IsPowerOnSetPoint = IsPowerOnSetPoint,
  159. IsControlTcBroken = IsControlTcBroken,
  160. IsMonitorTcBroken = IsMonitorTcBroken,
  161. Unit = Unit,
  162. DisplayWithUnit = true,
  163. FormatString = "F2",
  164. };
  165. return data;
  166. }
  167. }
  168. private DIAccessor _diPowerOnFeedback = null;
  169. private DIAccessor _diControlTcBroken;
  170. private DIAccessor _diMonitorTcBroken;
  171. private DOAccessor _doPowerOn = null;
  172. private AIAccessor _aiControlTcFeedback = null;
  173. private AIAccessor _aiMonitorTcFeedback = null;
  174. private AOAccessor _aoSetPoint = null;
  175. private AOAccessor _aoSetPointLimit = null;
  176. private R_TRIG _trigMonitorTcBroken = new R_TRIG();
  177. private R_TRIG _trigControlTcBroken = new R_TRIG();
  178. private bool _isFloatAioType = false;
  179. private SCConfigItem _scRange;
  180. private SCConfigItem _scEnableCalibration;
  181. private SCConfigItem _scCalibrationTable;
  182. private List<CalibrationItem> _calibrationTable = new List<CalibrationItem>();
  183. private string _previousSetting;
  184. public IoHeater(string module, XmlElement node, string ioModule = "")
  185. {
  186. base.Module = string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module");
  187. base.Name = node.GetAttribute("id");
  188. base.Display = node.GetAttribute("display");
  189. base.DeviceID = node.GetAttribute("schematicId");
  190. Unit = node.GetAttribute("unit");
  191. string scBasePath = node.GetAttribute("scBasePath");
  192. if (string.IsNullOrEmpty(scBasePath))
  193. scBasePath = $"{Module}.{Name}";
  194. else
  195. {
  196. scBasePath = scBasePath.Replace("{module}", Module);
  197. }
  198. _isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float");
  199. _diPowerOnFeedback = ParseDiNode("diPowerOnFeedback", node, ioModule);
  200. _diControlTcBroken = ParseDiNode("diControlTcBroken", node, ioModule);
  201. _diMonitorTcBroken = ParseDiNode("diMonitorTcBroken", node, ioModule);
  202. _doPowerOn = ParseDoNode("doPowerOn", node, ioModule);
  203. _aiControlTcFeedback = ParseAiNode("aiFeedback", node, ioModule);
  204. _aiMonitorTcFeedback = ParseAiNode("aiMonitor", node, ioModule);
  205. _aoSetPoint = ParseAoNode("aoSetPoint", node, ioModule);
  206. _aoSetPointLimit = ParseAoNode("aoSetPointLimit", node, ioModule);
  207. _scRange = ParseScNode("scRange", node, ioModule, $"{scBasePath}.{Name}.Range");
  208. _scEnableCalibration = SC.GetConfigItem($"{scBasePath}.{Name}.EnableCalibration");
  209. _scCalibrationTable = SC.GetConfigItem($"{scBasePath}.{Name}.CalibrationTable");
  210. }
  211. public void UpdateConfig(double setPointLimit)
  212. {
  213. SetPointLimit = setPointLimit;
  214. }
  215. public bool Initialize()
  216. {
  217. DATA.Subscribe(string.Format("Device.{0}.{1}", Module, Name), () => DeviceData);
  218. DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
  219. DEVICE.Register(String.Format("{0}.{1}", Name, AITHeaterOperation.SetPowerOnOff), (out string reason, int time, object[] param) =>
  220. {
  221. reason = "";
  222. bool isEnable = Convert.ToBoolean((string)param[0]);
  223. bool result = true;
  224. if (_doPowerOn != null)
  225. {
  226. result &= _doPowerOn.SetValue(isEnable, out reason);
  227. }
  228. if (result)
  229. reason = string.Format("Set Heater {0} Power {1}", Name, isEnable ? "On" : "Off");
  230. return result;
  231. });
  232. DEVICE.Register(String.Format("{0}.{1}", Name, AITHeaterOperation.Ramp), (out string reason, int time, object[] param) =>
  233. {
  234. float setpoint = (float)Convert.ToDouble((string)param[0]);
  235. if (setpoint > SetPointLimit || setpoint < 0)
  236. {
  237. reason = string.Format("Heater {0} temperature setpoint {1} is not valid, should be (0, {2})", Display, setpoint, SetPointLimit);
  238. return false;
  239. }
  240. ControlTcSetPoint = setpoint;
  241. reason = string.Format("Heater {0} Set to {1}", Display, setpoint);
  242. return true;
  243. });
  244. OP.Subscribe($"{Module}.{Name}.{AITHeaterOperation.Ramp}", (out string reason, int time, object[] param) =>
  245. {
  246. float setpoint = (float)Convert.ToDouble((string)param[0]);
  247. if (setpoint > SetPointLimit || setpoint < 0)
  248. {
  249. reason = string.Format("Heater {0} temperature setpoint {1} is not valid, should be (0, {2})", Display, setpoint, SetPointLimit);
  250. return false;
  251. }
  252. ControlTcSetPoint = setpoint;
  253. reason = string.Format("Heater {0} Set to {1}", Display, setpoint);
  254. return true;
  255. });
  256. UpdateCalibrationTable();
  257. return true;
  258. }
  259. public void Stop()
  260. {
  261. ControlTcSetPoint = 0;
  262. }
  263. public void Terminate()
  264. {
  265. }
  266. public void Monitor()
  267. {
  268. _trigControlTcBroken.CLK = IsControlTcBroken;
  269. if (_trigControlTcBroken.Q)
  270. {
  271. EV.PostMessage(Module, EventEnum.DefaultAlarm, string.Format("{0}, found control TC broken", Display));
  272. }
  273. _trigMonitorTcBroken.CLK = IsMonitorTcBroken;
  274. if (_trigMonitorTcBroken.Q)
  275. {
  276. EV.PostMessage(Module, EventEnum.DefaultAlarm, string.Format("{0}, found monitor TC broken", Display));
  277. }
  278. }
  279. public void Reset()
  280. {
  281. _trigControlTcBroken.RST = true;
  282. _trigMonitorTcBroken.RST = true;
  283. UpdateCalibrationTable();
  284. }
  285. public void UpdateCalibrationTable()
  286. {
  287. if (_scCalibrationTable == null)
  288. return;
  289. if (_previousSetting == _scCalibrationTable.StringValue)
  290. return;
  291. _previousSetting = _scCalibrationTable.StringValue;
  292. if (string.IsNullOrEmpty(_previousSetting))
  293. {
  294. _calibrationTable = new List<CalibrationItem>();
  295. return;
  296. }
  297. var table = new List<Tuple<float, float>>();
  298. string[] items = _previousSetting.Split(';');
  299. for (int i = 0; i < items.Length; i++)
  300. {
  301. string itemValue = items[i];
  302. if (!string.IsNullOrEmpty(itemValue))
  303. {
  304. string[] pairValue = itemValue.Split('#');
  305. if (pairValue.Length == 2)
  306. {
  307. if (float.TryParse(pairValue[0], out float rawData)
  308. && float.TryParse(pairValue[1], out float calibrationData))
  309. {
  310. table.Add(Tuple.Create(rawData, calibrationData));
  311. }
  312. }
  313. }
  314. }
  315. table = table.OrderBy(x => x.Item1).ToList();
  316. var calibrationTable = new List<CalibrationItem>();
  317. for (int i = 0; i < table.Count; i++)
  318. {
  319. if (i == 0 && table[0].Item1 > 0.001)
  320. {
  321. calibrationTable.Add(new CalibrationItem()
  322. {
  323. RawFrom = 0,
  324. CalibrationFrom = 0,
  325. RawTo = table[0].Item1,
  326. CalibrationTo = table[0].Item2,
  327. });
  328. }
  329. if (i == table.Count - 1)
  330. {
  331. float maxValue = _scRange != null ? (float)_scRange.DoubleValue : table[i].Item2 * 2;
  332. calibrationTable.Add(new CalibrationItem()
  333. {
  334. RawFrom = table[i].Item1,
  335. RawTo = table[i].Item2,
  336. CalibrationFrom = maxValue,
  337. CalibrationTo = maxValue,
  338. });
  339. continue;
  340. }
  341. calibrationTable.Add(new CalibrationItem()
  342. {
  343. RawFrom = table[i].Item1,
  344. CalibrationFrom = table[i].Item2,
  345. RawTo = table[i + 1].Item1,
  346. CalibrationTo = table[i + 1].Item2,
  347. });
  348. }
  349. _calibrationTable = calibrationTable;
  350. }
  351. private float CalibrationData(float value, bool output)
  352. {
  353. //default enable
  354. if (_scEnableCalibration != null && !_scEnableCalibration.BoolValue)
  355. return value;
  356. if (_scCalibrationTable == null || !_calibrationTable.Any())
  357. return value;
  358. float ret = value;
  359. if (output)
  360. {
  361. var item = _calibrationTable.FirstOrDefault(x => x.RawFrom <= value && x.RawTo >= value);
  362. if (item != null && Math.Abs(item.RawTo - item.RawFrom) > 0.01)
  363. {
  364. var slope = (item.CalibrationTo - item.CalibrationFrom) / (item.RawTo - item.RawFrom);
  365. ret = (ret - item.RawFrom) * slope + item.CalibrationFrom;
  366. }
  367. }
  368. else
  369. {
  370. var item = _calibrationTable.FirstOrDefault(x => x.CalibrationFrom <= value && x.CalibrationTo >= value);
  371. if (item != null && item.CalibrationTo == 0 && item.CalibrationFrom == 0 && value > 0)
  372. item = _calibrationTable[_calibrationTable.Count - 1];
  373. if (item != null && Math.Abs(item.CalibrationTo - item.CalibrationFrom) > 0.01)
  374. {
  375. var slope = (item.RawTo - item.RawFrom) / (item.CalibrationTo - item.CalibrationFrom);
  376. ret = (ret - item.CalibrationFrom) * slope + item.RawFrom;
  377. }
  378. }
  379. if (ret < 0)
  380. return 0;
  381. if (ret >= float.MaxValue || (_scRange != null && ret > _scRange.DoubleValue))
  382. ret = value;
  383. return ret;
  384. }
  385. }
  386. }