PowerSupplierGoldModbusDevice.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.RT.SCCore;
  3. using Aitex.Core.Util;
  4. using DocumentFormat.OpenXml.InkML;
  5. using MECF.Framework.Common.CommonData.PowerSupplier;
  6. using MECF.Framework.Common.Communications;
  7. using MECF.Framework.Common.Net;
  8. using System;
  9. using System.Collections.Concurrent;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Reflection;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. namespace MECF.Framework.Common.Device.PowerSupplier
  16. {
  17. public class PowerSupplierGoldModbusDevice : JetMessageTcpClient<PowerSupplierTcpModbusMessage, PowerSupplierCommand>,IPowerSupplierDevice
  18. {
  19. #region 常量
  20. private const short CURRENT_SETTING_ADDRESS = 0x6102;
  21. private const short OUTPUT_CONTROL_ADDRESS = 0x0110;
  22. private const short STEP_PERIOD_ADDRESS = 0x77D0;
  23. private const short STEP_PERIOD_START_ADDRESS = 0x7C50;
  24. private const short VOLTAGE_OUTPUT_ADDRESS = 0x0201;
  25. private const short POWER_CONTROL_ADDRESS = 0x0113;
  26. private const short POWER_RUN_MODEL_ADDRESS = 0x0111;
  27. /// <summary>
  28. /// 电源状态(00-cv输出,01-cc输出)
  29. /// </summary>
  30. private const short POWER_STATUS_ADDRESS = 0x0200;
  31. private const string SET_POINT = "SetPoint";
  32. private const string CURRENT = "Current";
  33. private const string VOLTAGE = "Voltage";
  34. private const string ENABLED = "Enabled";
  35. private const string POWER_STATUS = "PowerStatus";
  36. private const string POWER_CONTROL = "PowerControl";
  37. private const string POWER_RUN_MODEL = "PowerRunModel";
  38. /// <summary>
  39. /// 步阶数据数量
  40. /// </summary>
  41. private const int STEP_PERIOD_LENGTH = 12;
  42. #endregion
  43. #region 内部变量
  44. private string _name;
  45. private string _lastErrorMsg = "";
  46. private bool _isFirstConnected = false;
  47. #endregion
  48. /// <summary>
  49. /// 构造函数
  50. /// </summary>
  51. /// <param name="ip"></param>
  52. /// <param name="port"></param>
  53. public PowerSupplierGoldModbusDevice(string name, string ip, int port,int receiveTimeout,int sendTimeout) : base(ip, port)
  54. {
  55. ReceiveTimeout = receiveTimeout;
  56. SendTimeout = sendTimeout;
  57. ReconnectInterval = 3000;
  58. ConnectTimeout = 1000;
  59. _name = name;
  60. Name = _name;
  61. EventId = eEvent.INFO_POWERSUPPLIER;
  62. }
  63. /// <summary>
  64. /// 连接
  65. /// </summary>
  66. /// <returns></returns>
  67. public void Start()
  68. {
  69. Connect();
  70. if (!_isFirstConnected)
  71. {
  72. _isFirstConnected = true;
  73. }
  74. }
  75. /// <summary>
  76. /// 设置通道输出开关控制
  77. /// </summary>
  78. /// <param name="channel"></param>
  79. /// <param name="currentValue"></param>
  80. /// <returns></returns>
  81. public bool SetChannelOutputSwitchControl(byte channel, bool enabled)
  82. {
  83. PowerSupplierCommand command = new PowerSupplierCommand();
  84. command.Channel = channel;
  85. command.CommandCode = 0x06;
  86. command.Address = (ushort)(OUTPUT_CONTROL_ADDRESS);
  87. command.Datas = new ushort[] { enabled ? (ushort)01 : (ushort)00 };
  88. return SetOperation(command);
  89. }
  90. /// <summary>
  91. /// 设置电源控制
  92. /// </summary>
  93. /// <param name="channel"></param>
  94. /// <param name="currentValue"></param>
  95. /// <returns></returns>
  96. public bool SetChannelPowerControl(byte channel, byte remoteControl)
  97. {
  98. PowerSupplierCommand command = new PowerSupplierCommand();
  99. command.Channel = channel;
  100. command.CommandCode = 0x06;
  101. command.Address = (ushort)(POWER_CONTROL_ADDRESS);
  102. command.Datas = new ushort[] { remoteControl };
  103. return SetOperation(command);
  104. }
  105. /// <summary>
  106. /// 设置电源运行模式
  107. /// </summary>
  108. /// <param name="channel"></param>
  109. /// <param name="currentValue"></param>
  110. /// <returns></returns>
  111. public bool SetChannelPowerRunmodelControl(byte channel, byte model)
  112. {
  113. PowerSupplierCommand command = new PowerSupplierCommand();
  114. command.Channel = channel;
  115. command.CommandCode = 0x06;
  116. command.Address = (ushort)(POWER_RUN_MODEL_ADDRESS);
  117. command.Datas = new ushort[] { model };
  118. return SetOperation(command);
  119. }
  120. /// <summary>
  121. /// 设置步阶数据
  122. /// </summary>
  123. /// <param name="channel"></param>
  124. /// <param name="stepDatas"></param>
  125. public bool SetStepPeriod(byte channel, List<PowerSupplierStepPeriodData> stepDatas, int scale, int voltageUnitSetScale)
  126. {
  127. PowerSupplierCommand command = new PowerSupplierCommand();
  128. command.Channel = channel;
  129. command.CommandCode = 0x10;
  130. command.Address = (ushort)STEP_PERIOD_ADDRESS;
  131. command.RegisterCount = (ushort)(STEP_PERIOD_LENGTH * stepDatas.Count);
  132. command.Datas = new ushort[STEP_PERIOD_LENGTH * stepDatas.Count];
  133. for (int i = 0; i < stepDatas.Count; i++)
  134. {
  135. PowerSupplierStepPeriodData data = stepDatas[i];
  136. command.Datas[0 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(data.Voltage * voltageUnitSetScale, 0)/0x10000);
  137. command.Datas[1 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(data.Voltage * voltageUnitSetScale, 0) % 0x10000);
  138. command.Datas[2 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(data.Current * scale, 0)/0x10000);
  139. command.Datas[3 + STEP_PERIOD_LENGTH * i] = (ushort)(Math.Round(data.Current * scale, 0) % 0x10000);
  140. command.Datas[4 + STEP_PERIOD_LENGTH * i] = 0;
  141. command.Datas[5 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Hour;
  142. command.Datas[6 + STEP_PERIOD_LENGTH * i] = 0;
  143. command.Datas[7 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Minute;
  144. command.Datas[8 + STEP_PERIOD_LENGTH * i] = 0;
  145. command.Datas[9 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Second;
  146. command.Datas[10 + STEP_PERIOD_LENGTH * i] = 0;
  147. command.Datas[11 + STEP_PERIOD_LENGTH * i] = stepDatas[i].Microsecond;
  148. }
  149. return SetOperation(command);
  150. }
  151. /// <summary>
  152. /// 启动步阶
  153. /// </summary>
  154. /// <param name="channel"></param>
  155. /// <param name="startStep"></param>
  156. /// <param name="endStep"></param>
  157. /// <param name="cycle"></param>
  158. public bool StartStepPeriod(byte channel, ushort startStep, ushort endStep, ushort cycle)
  159. {
  160. PowerSupplierCommand command = new PowerSupplierCommand();
  161. command.Channel = channel;
  162. command.CommandCode = 0x10;
  163. command.Address = (ushort)STEP_PERIOD_START_ADDRESS;
  164. command.RegisterCount = 6;
  165. command.Datas = new ushort[6] {0,startStep, 0,endStep,0,cycle };
  166. return SetOperation(command);
  167. }
  168. /// <summary>
  169. /// 设置电流
  170. /// </summary>
  171. /// <param name="channel"></param>
  172. /// <param name="currentValue"></param>
  173. /// <returns></returns>
  174. public bool SetCurrentValue(byte channel, int currentValue)
  175. {
  176. PowerSupplierCommand command = new PowerSupplierCommand();
  177. command.Channel = channel;
  178. command.CommandCode = 0x10;
  179. command.Address = (ushort)(CURRENT_SETTING_ADDRESS);
  180. command.RegisterCount = 2;//2N N-寄存器地址数据
  181. ushort[] ushorts = new ushort[2];
  182. ushorts[0] = (ushort)(currentValue / 0x10000);//高位
  183. ushorts[1] = (ushort)(currentValue % 0x10000);//低位
  184. command.Datas = ushorts;
  185. return SetOperation(command);
  186. }
  187. /// <summary>
  188. /// 设置电源状态
  189. /// </summary>
  190. /// <param name="channel"></param>
  191. /// <param name="currentValue"></param>
  192. /// <returns></returns>
  193. public bool SetChannelPowerStatus(byte channel, byte powerStatus)
  194. {
  195. PowerSupplierCommand command = new PowerSupplierCommand();
  196. command.Channel = channel;
  197. command.CommandCode = 0x06;
  198. command.Address = (ushort)(POWER_STATUS_ADDRESS);
  199. command.Datas = new ushort[] { powerStatus };
  200. return SetOperation(command);
  201. }
  202. /// <summary>
  203. /// 获取通道输出开关控制
  204. /// </summary>
  205. /// <param name="channel"></param>
  206. /// <returns></returns>
  207. public void GetChannelOutput(byte channel)
  208. {
  209. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  210. applyCommand.Channel = channel;
  211. applyCommand.CommandCode = 0x03;
  212. applyCommand.Address = (ushort)(OUTPUT_CONTROL_ADDRESS);
  213. applyCommand.RegisterCount = 1;
  214. applyCommand.Variables.Add(ENABLED, (0, 1));
  215. ApplyDataOperation(applyCommand);
  216. }
  217. /// <summary>
  218. /// 获取通道电源控制
  219. /// </summary>
  220. /// <param name="channel"></param>
  221. /// <returns></returns>
  222. public void GetChannelPowerControl(byte channel)
  223. {
  224. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  225. applyCommand.Channel = channel;
  226. applyCommand.CommandCode = 0x03;
  227. applyCommand.Address = (ushort)(POWER_CONTROL_ADDRESS);
  228. applyCommand.RegisterCount = 1;
  229. applyCommand.Variables.Add(POWER_CONTROL, (0, 1));
  230. ApplyDataOperation(applyCommand);
  231. }
  232. /// <summary>
  233. /// 获取通道电流设置数值
  234. /// </summary>
  235. /// <param name="channel"></param>
  236. /// <returns></returns>
  237. public void GetChannelCurrentSetting(byte channel)
  238. {
  239. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  240. applyCommand.Channel = channel;
  241. applyCommand.CommandCode = 0x03;
  242. applyCommand.Address = (ushort)(CURRENT_SETTING_ADDRESS);
  243. applyCommand.RegisterCount = 2;
  244. applyCommand.Variables.Add(SET_POINT, (0, 2));
  245. ApplyDataOperation(applyCommand);
  246. }
  247. /// <summary>
  248. /// 获取电源状态设置数值
  249. /// </summary>
  250. /// <param name="channel"></param>
  251. /// <returns></returns>
  252. public void GetChannelPowerStatus(byte channel)
  253. {
  254. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  255. applyCommand.Channel = channel;
  256. applyCommand.CommandCode = 0x03;
  257. applyCommand.Address = (ushort)(POWER_STATUS_ADDRESS);
  258. applyCommand.RegisterCount = 1;
  259. applyCommand.Variables.Add(POWER_STATUS, (0, 1));
  260. ApplyDataOperation(applyCommand);
  261. }
  262. /// <summary>
  263. /// 获取电源运行模式
  264. /// </summary>
  265. /// <param name="channel"></param>
  266. /// <returns></returns>
  267. public void GetChannelPowerRunModel(byte channel)
  268. {
  269. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  270. applyCommand.Channel = channel;
  271. applyCommand.CommandCode = 0x03;
  272. applyCommand.Address = (ushort)(POWER_RUN_MODEL_ADDRESS);
  273. applyCommand.RegisterCount = 1;
  274. applyCommand.Variables.Add(POWER_RUN_MODEL, (0, 1));
  275. ApplyDataOperation(applyCommand);
  276. }
  277. /// <summary>
  278. /// 申请电压和电流数值
  279. /// </summary>
  280. /// <param name="channel"></param>
  281. /// <returns></returns>
  282. public void GetChannelVoltageAndCurrent(byte channel)
  283. {
  284. PowerSupplierCommand applyCommand = new PowerSupplierCommand();
  285. applyCommand.Channel = channel;
  286. applyCommand.CommandCode = 0x03;
  287. applyCommand.Address = (ushort)(VOLTAGE_OUTPUT_ADDRESS);
  288. applyCommand.RegisterCount = 4;
  289. applyCommand.Variables.Add(VOLTAGE, (0, 2));
  290. applyCommand.Variables.Add(CURRENT, (2, 2));
  291. ApplyDataOperation(applyCommand);
  292. }
  293. /// <summary>
  294. /// 设置操作
  295. /// </summary>
  296. /// <param name="command"></param>
  297. /// <returns></returns>
  298. private bool SetOperation(PowerSupplierCommand command)
  299. {
  300. if (SC.ContainsItem("Log.EnablePowerSupplierLog"))
  301. {
  302. LogEnabled = SC.GetValue<bool>("Log.EnablePowerSupplierLog");
  303. }
  304. if (Connected)
  305. {
  306. NetResult netResult = SetData(command);
  307. if (!netResult.IsSuccess)
  308. {
  309. WriteErrMsg($"write write {command.Address.ToString("X2")} value {command.Datas[0]} failed,{netResult.Message}");
  310. return false;
  311. }
  312. return true;
  313. }
  314. else
  315. {
  316. NetResult netResult = Connect();
  317. if (netResult.IsSuccess)
  318. {
  319. netResult = SetData(command);
  320. if (!netResult.IsSuccess)
  321. {
  322. WriteErrMsg($"write {command.Address.ToString("X2")} value {command.Datas[0]} failed,{netResult.Message}");
  323. return false;
  324. }
  325. return true;
  326. }
  327. else
  328. {
  329. WriteErrMsg("connect failed");
  330. return false;
  331. }
  332. }
  333. }
  334. /// <summary>
  335. /// 申请数据操作
  336. /// </summary>
  337. /// <param name="command"></param>
  338. private void ApplyDataOperation(PowerSupplierCommand command)
  339. {
  340. if (SC.ContainsItem("Log.EnablePowerSupplierLog"))
  341. {
  342. LogEnabled = SC.GetValue<bool>("Log.EnablePowerSupplierLog");
  343. }
  344. if (!Connected)
  345. {
  346. NetResult connectResult = Connect();
  347. if (!connectResult.IsSuccess)
  348. {
  349. WriteErrMsg("connect failed");
  350. return;
  351. }
  352. }
  353. NetResult<PowerSupplierCommand> netResult = ApplyData(command);
  354. if (!netResult.IsSuccess)
  355. {
  356. WriteErrMsg($"apply {command.Address.ToString("X2")} failed,{netResult.Message}");
  357. return;
  358. }
  359. if (netResult.Data.Datas != null)
  360. {
  361. Dictionary<string, (int, int)> dictionary = command.Variables;
  362. List<string> keys = dictionary.Keys.ToList();
  363. foreach (string item in keys)
  364. {
  365. var result = dictionary[item];
  366. if (item == ENABLED)
  367. {
  368. PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, ENABLED, netResult.Data.Datas[result.Item1] == 0x01);
  369. }
  370. else
  371. {
  372. if (result.Item2 == 1)
  373. {
  374. PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, item, netResult.Data.Datas[result.Item1]);
  375. }
  376. else if (result.Item2 == 2)
  377. {
  378. int value = netResult.Data.Datas[result.Item1] * 0xFFFF + netResult.Data.Datas[result.Item1 + 1];
  379. PowerSupplierDeviceConfigManager.Instance.UpdateModuleVariable(_name, command.Channel, item, value);
  380. }
  381. }
  382. }
  383. }
  384. }
  385. /// <summary>
  386. /// 写错误日志
  387. /// </summary>
  388. /// <param name="msg"></param>
  389. private void WriteErrMsg(string msg)
  390. {
  391. if (msg != _lastErrorMsg)
  392. {
  393. _lastErrorMsg = msg;
  394. LOG.WriteLog(eEvent.ERR_POWERSUPPLIER, _name, msg);
  395. }
  396. }
  397. }
  398. }