OilSourceService.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. using IPLCConnect;
  2. using OilSourceModel;
  3. using OilSourceModel.Models;
  4. using SQLite;
  5. using System.Diagnostics.CodeAnalysis;
  6. using System.Net.NetworkInformation;
  7. using System.Net.Sockets;
  8. namespace OilSourceService
  9. {
  10. public sealed class OilSourceService : IOilSourceService.IOilSourceService
  11. {
  12. public OilSourceService()
  13. {
  14. _timer = new System.Timers.Timer(5000);
  15. _timer.Elapsed += Timer_Elapsed;
  16. _timer.Enabled = false;
  17. _timer.AutoReset = true;
  18. _timer.Stop();
  19. }
  20. private object locker = new object();
  21. private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
  22. {
  23. try
  24. {
  25. Ping ping = new Ping();
  26. if (ping.Send(config.IP).Status == IPStatus.Success)
  27. {
  28. //_PLCConnect.Init(oilSourceConfig.IP, oilSourceConfig.Port);
  29. lock (locker)
  30. {
  31. PLCConnect?.Connect();
  32. }
  33. }
  34. }
  35. catch
  36. {
  37. }
  38. }
  39. /// <summary>
  40. /// PLC断开连接后定时重连PLC计时器
  41. /// </summary>
  42. private System.Timers.Timer _timer = new System.Timers.Timer(5000);
  43. [AllowNull]
  44. public Action<bool> ConnectChanged { get; set; }
  45. /// <summary>
  46. /// 油源循环锁,当油源与PLC断开连接后自动阻塞轮询线程
  47. /// </summary>
  48. private ManualResetEvent OilLock = new ManualResetEvent(true);
  49. public OilSourceStatusModel OilSourceStatus { get; } = new OilSourceStatusModel();
  50. private OilSourceModel.Models.OilSourceConfigModel config = new OilSourceModel.Models.OilSourceConfigModel();
  51. private CancellationTokenSource _cts= new CancellationTokenSource();
  52. [AllowNull]
  53. public IPLCConnect.IPLCConnect PLCConnect { get; private set; }
  54. [AllowNull]
  55. public ICommunication.ICommunication Communication { get; private set; }
  56. [AllowNull]
  57. public SQLiteConnection DbConnection { get; private set; }
  58. public bool IsStart { get; private set; } = false;
  59. public void Init(ICommunication.ICommunication communication, SQLiteConnection dbConnection)
  60. {
  61. Communication = communication;
  62. DbConnection = dbConnection;
  63. ReadModel();
  64. Communication.GetEvent(Topic.CircuitPressure)?.Subscrip((sender, args) =>
  65. {
  66. if (args.Data.Length >= 2 && args.Data[0] is int index && args.Data[1] is float pressure)
  67. {
  68. if (!config.MainPumpAddress[index].IsPressureEnabled) return;
  69. PLCConnect?.Write(config.MainPumpAddress[index].Address, pressure);
  70. }
  71. });
  72. Communication.GetEvent(Topic.CircuitStart)?.Subscrip((sender, args) =>
  73. {
  74. if (args.Data.Length >= 2 && args.Data[0] is int index && args.Data[1] is bool state)
  75. {
  76. if (!config.MainPumpAddress[index].IsEnabled) return;
  77. if (state)
  78. {
  79. SetLevel(config.MainPumpAddress[index].StartAddress, true);
  80. }
  81. else
  82. {
  83. SetLevel(config.MainPumpAddress[index].StopAddress, true);
  84. }
  85. }
  86. });
  87. Communication.GetEvent(Topic.CircuitLoad)?.Subscrip((sender, args) =>
  88. {
  89. if (args.Data.Length >= 2 && args.Data[0] is int index && args.Data[1] is bool state)
  90. {
  91. if (!config.MainPumpAddress[index].IsLoadEnabled) return;
  92. if (state)
  93. {
  94. SetLevel(config.MainPumpAddress[index].LoadAddress, true);
  95. }
  96. else
  97. {
  98. SetLevel(config.MainPumpAddress[index].UnLoadAddress, true);
  99. }
  100. }
  101. });
  102. Communication.GetEvent(Topic.ForerunnerPressure)?.Subscrip((sender, args) =>
  103. {
  104. if (args.Data.Length >= 1 && args.Data[0] is float pressure)
  105. {
  106. if (!config.ForerunnerAddress.IsPressureEnabled) return;
  107. PLCConnect?.Write(config.ForerunnerAddress.Address, pressure);
  108. }
  109. });
  110. Communication.GetEvent(Topic.ForerunnerStart)?.Subscrip((sender, args) =>
  111. {
  112. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  113. {
  114. if (!config.ForerunnerAddress.IsEnabled) return;
  115. if (state)
  116. {
  117. SetLevel(config.ForerunnerAddress.StartAddress, true);
  118. }
  119. else
  120. {
  121. SetLevel(config.ForerunnerAddress.StopAddress, true);
  122. }
  123. }
  124. });
  125. Communication.GetEvent(Topic.ForerunnerLoad)?.Subscrip((sender, args) =>
  126. {
  127. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  128. {
  129. if (!config.ForerunnerAddress.IsLoadEnabled) return;
  130. if (state)
  131. {
  132. SetLevel(config.ForerunnerAddress.LoadAddress, true);
  133. }
  134. else
  135. {
  136. SetLevel(config.ForerunnerAddress.UnLoadAddress, true);
  137. }
  138. }
  139. });
  140. Communication.GetEvent(Topic.AssistantPressure)?.Subscrip((sender, args) =>
  141. {
  142. if (args.Data.Length >= 1 && args.Data[0] is float pressure)
  143. {
  144. if (!config.AssistantAddress.IsPressureEnabled) return;
  145. PLCConnect?.Write(config.AssistantAddress.Address, pressure);
  146. }
  147. });
  148. Communication.GetEvent(Topic.AssistantStart)?.Subscrip((sender, args) =>
  149. {
  150. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  151. {
  152. if (!config.AssistantAddress.IsEnabled) return;
  153. if (state)
  154. {
  155. SetLevel(config.AssistantAddress.StartAddress, true);
  156. }
  157. else
  158. {
  159. SetLevel(config.AssistantAddress.StopAddress, true);
  160. }
  161. }
  162. });
  163. Communication.GetEvent(Topic.AssistantLoad)?.Subscrip((sender, args) =>
  164. {
  165. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  166. {
  167. if (!config.AssistantAddress.IsLoadEnabled) return;
  168. if (state)
  169. {
  170. SetLevel(config.AssistantAddress.LoadAddress, true);
  171. }
  172. else
  173. {
  174. SetLevel(config.AssistantAddress.UnLoadAddress, true);
  175. }
  176. }
  177. });
  178. Communication.GetEvent(Topic.CirculatePressure)?.Subscrip((sender, args) =>
  179. {
  180. if (args.Data.Length >= 1 && args.Data[0] is float pressure)
  181. {
  182. if (!config.CirculateAddress.IsPressureEnabled) return;
  183. PLCConnect?.Write(config.CirculateAddress.Address, pressure);
  184. }
  185. });
  186. Communication.GetEvent(Topic.CirculateStart)?.Subscrip((sender, args) =>
  187. {
  188. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  189. {
  190. if (!config.CirculateAddress.IsEnabled) return;
  191. if (state)
  192. {
  193. SetLevel(config.CirculateAddress.StartAddress, true);
  194. }
  195. else
  196. {
  197. SetLevel(config.CirculateAddress.StopAddress, true);
  198. }
  199. }
  200. });
  201. Communication.GetEvent(Topic.CirculateLoad)?.Subscrip((sender, args) =>
  202. {
  203. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  204. {
  205. if (!config.CirculateAddress.IsLoadEnabled) return;
  206. if (state)
  207. {
  208. SetLevel(config.CirculateAddress.LoadAddress, true);
  209. }
  210. else
  211. {
  212. SetLevel(config.CirculateAddress.UnLoadAddress, true);
  213. }
  214. }
  215. });
  216. Communication.GetEvent(Topic.OilEmergencyStop)?.Subscrip((sender, args) =>
  217. {
  218. if (args.Data.Length >= 1 && args.Data[0] is bool state)
  219. {
  220. if (state)
  221. {
  222. SetLevel(config.EmergencyStopAddress, true);
  223. }
  224. else
  225. {
  226. SetLevel(config.EmergencyStopAddress, true);
  227. }
  228. }
  229. });
  230. }
  231. private async void SetLevel(string address, bool value)
  232. {
  233. if (config.LevelLogic == LevelLogic.Level)
  234. {
  235. PLCConnect?.Writebit(address, value);
  236. }
  237. else
  238. {
  239. PLCConnect?.Writebit(address, !value);
  240. await Task.Delay(config.LevelTime);
  241. PLCConnect?.Writebit(address, value);
  242. }
  243. }
  244. private void ReadModel()
  245. {
  246. DbConnection.CreateTable<OilSourceModel.Models.OilSourceConfigModel>();
  247. config = DbConnection.Table<OilSourceModel.Models.OilSourceConfigModel>()?.FirstOrDefault() ?? new OilSourceModel.Models.OilSourceConfigModel();
  248. DbConnection.CreateTable<OilSourcePumpAddressConfig>(tableName: nameof(config.MainPumpAddress));
  249. config.MainPumpAddress = DbConnection.Table<OilSourcePumpAddressConfig>(tableName: nameof(config.MainPumpAddress))?.Where(x=>!string.IsNullOrEmpty(x.Address) && x.IsEnabled)?.ToList() ?? new List<OilSourcePumpAddressConfig>();
  250. DbConnection.CreateTable<OilSourcePumpAddressConfig>(tableName: nameof(config.ForerunnerAddress));
  251. config.ForerunnerAddress = DbConnection.Table<OilSourcePumpAddressConfig>(tableName: nameof(config.ForerunnerAddress))?.FirstOrDefault() ?? new OilSourcePumpAddressConfig();
  252. DbConnection.CreateTable<OilSourcePumpAddressConfig>(tableName:nameof(config.CirculateAddress));
  253. config.CirculateAddress = DbConnection.Table<OilSourcePumpAddressConfig>(tableName: nameof(config.CirculateAddress))?.FirstOrDefault() ?? new OilSourcePumpAddressConfig();
  254. DbConnection.CreateTable<OilSourcePumpAddressConfig>(tableName: nameof(config.AssistantAddress));
  255. config.AssistantAddress = DbConnection.Table<OilSourcePumpAddressConfig>(tableName: nameof(config.AssistantAddress))?.FirstOrDefault() ?? new OilSourcePumpAddressConfig();
  256. DbConnection.CreateTable<OilSourceAnalogAddressConfig>(tableName: nameof(config.AnalogAddress));
  257. config.AnalogAddress = DbConnection.Table<OilSourceAnalogAddressConfig>(tableName: nameof(config.AnalogAddress))?.Where(x=>!string.IsNullOrEmpty(x.ValueAddress) && !string.IsNullOrEmpty(x.Name))?.ToList() ?? new List<OilSourceAnalogAddressConfig>();
  258. DbConnection.CreateTable<ErrorAddressConfig>(tableName: nameof(config.ErrorAddress));
  259. config.ErrorAddress = DbConnection.Table<ErrorAddressConfig>(tableName: nameof(config.ErrorAddress))?.Where(x=>!string.IsNullOrEmpty(x.Address) && !string.IsNullOrEmpty(x.Name))?.ToList() ?? new List<ErrorAddressConfig>();
  260. SaveModel();
  261. InitOilSourceStatus();
  262. if (!OilSourceStatus.IsEnabled) return;
  263. var plcs = IModel.Tools.PluginsLoader.Defalut.Load<IPLCConnect.IPLCConnect>(AppDomain.CurrentDomain.BaseDirectory);
  264. PLCConnect = plcs.FirstOrDefault(x => x.Protocol == config.Protocol);
  265. if (PLCConnect == null)
  266. {
  267. OilSourceStatus.IsEnabled = false;
  268. return;
  269. }
  270. try
  271. {
  272. PLCConnect.StatusChanged += PLCConnect_StatusChanged;
  273. PLCConnect.Init(config.IP, config.Port);
  274. OilLock.Set();
  275. Task.Run(async () =>
  276. {
  277. _cts = new CancellationTokenSource();
  278. while(!_cts.IsCancellationRequested)
  279. {
  280. OilLock.WaitOne();
  281. ReadOilSourceData();
  282. await Task.Delay(50);
  283. }
  284. });
  285. }
  286. catch
  287. {
  288. OilSourceStatus.IsEnabled = false;
  289. }
  290. }
  291. private void RepeatConnectPLC()
  292. {
  293. _timer.Enabled = true;
  294. _timer.Start();
  295. }
  296. private void SaveModel()
  297. {
  298. }
  299. private void InitOilSourceStatus()
  300. {
  301. if (config.AnalogAddress.Count > 0)
  302. {
  303. OilSourceStatus.OilSourceAnalogs.AddRange(config.AnalogAddress.Select(x=>new OilSourceAnalogModel()
  304. {
  305. Name = x.Name,
  306. Unit = x.Unit,
  307. }));
  308. }
  309. if(config.MainPumpAddress.Count>0)
  310. {
  311. OilSourceStatus.Circuit.AddRange(config.MainPumpAddress.Select(x => new CircuitModel()
  312. {
  313. Name = x.Name,
  314. IsEnable=x.IsEnabled,
  315. IsEnableLoad = x.IsLoadEnabled,
  316. IsEnablePressure = x.IsPressureEnabled,
  317. }));
  318. }
  319. OilSourceStatus.Circulate.Name = config.CirculateAddress.Name;
  320. OilSourceStatus.Circulate.IsEnableLoad = config.CirculateAddress.IsLoadEnabled;
  321. OilSourceStatus.Circulate.IsEnable = config.CirculateAddress.IsEnabled;
  322. OilSourceStatus.Circulate.IsEnablePressure = config.CirculateAddress.IsPressureEnabled;
  323. OilSourceStatus.Forerunner.Name = config.ForerunnerAddress.Name;
  324. OilSourceStatus.Forerunner.IsEnableLoad = config.ForerunnerAddress.IsLoadEnabled;
  325. OilSourceStatus.Forerunner.IsEnable = config.ForerunnerAddress.IsEnabled;
  326. OilSourceStatus.Forerunner.IsEnablePressure = config.ForerunnerAddress.IsPressureEnabled;
  327. OilSourceStatus.Assistant.Name = config.AssistantAddress.Name;
  328. OilSourceStatus.Assistant.IsEnableLoad = config.AssistantAddress.IsLoadEnabled;
  329. OilSourceStatus.Assistant.IsEnable = config.AssistantAddress.IsEnabled;
  330. OilSourceStatus.Assistant.IsEnablePressure = config.AssistantAddress.IsPressureEnabled;
  331. if(config.ErrorAddress.Count>0)
  332. {
  333. OilSourceStatus.OilErrors.AddRange(config.ErrorAddress.Select(x => new ErrorInfoModel()
  334. {
  335. Name = x.Name,
  336. }));
  337. }
  338. OilSourceStatus.IsEnabled = config.IsEnabled;
  339. }
  340. private void PLCConnect_StatusChanged(object? sender, bool e)
  341. {
  342. if (OilSourceStatus.IsConnect == e) return;
  343. ConnectChanged?.Invoke(e);
  344. OilSourceStatus.IsConnect = e;
  345. if(e)
  346. {
  347. OilLock.Reset();
  348. _timer.Stop();
  349. }
  350. else
  351. {
  352. OilLock.Set();
  353. RepeatConnectPLC();
  354. }
  355. }
  356. public void Start()
  357. {
  358. if (PLCConnect == null) return;
  359. if (PLCConnect.IsConnected) return;
  360. try
  361. {
  362. PLCConnect.Connect();
  363. }
  364. catch
  365. {
  366. }
  367. }
  368. public void ReadOilSourceData()
  369. {
  370. lock (locker)
  371. {
  372. if (!OilSourceStatus.IsEnabled || PLCConnect == null || !PLCConnect.IsConnected)
  373. {
  374. return;
  375. }
  376. for (int i = 0; i < OilSourceStatus.Circuit.Count; i++)
  377. {
  378. OilSourceStatus.Circuit[i].IsStart = PLCConnect.ReadBit(config.MainPumpAddress[i].IsStartAddress);
  379. //OilSourceStatus.Circuit[i].Pressure = _PLCConnect.Read<float>(oilSourceConfig.MainPumpAddress[i].Address);
  380. OilSourceStatus.Circuit[i].IsLoadPressure = PLCConnect.ReadBit(config.MainPumpAddress[i].IsLoadAddress);
  381. }
  382. OilSourceStatus.Circulate.IsLoadPressure = PLCConnect.ReadBit(config.CirculateAddress.IsLoadAddress);
  383. OilSourceStatus.Circulate.IsStart = PLCConnect.ReadBit(config.CirculateAddress.IsStartAddress);
  384. OilSourceStatus.Forerunner.IsStart = PLCConnect.ReadBit(config.ForerunnerAddress.IsStartAddress);
  385. OilSourceStatus.Forerunner.IsLoadPressure = PLCConnect.ReadBit(config.ForerunnerAddress.IsLoadAddress);
  386. for (int i = 0; i < OilSourceStatus.OilErrors.Count; i++)
  387. {
  388. OilSourceStatus.OilErrors[i].Status = PLCConnect.ReadBit(config.ErrorAddress[i].Address);
  389. }
  390. OilSourceStatus.IsRemote = PLCConnect.ReadBit(config.IsRemoteAddress);
  391. for (int i = 0; i < OilSourceStatus.OilSourceAnalogs.Count; i++)
  392. {
  393. OilSourceStatus.OilSourceAnalogs[i].Value = PLCConnect.Read<float>(config.AnalogAddress[i].ValueAddress);
  394. OilSourceStatus.OilSourceAnalogs[i].IsLowerError = PLCConnect.ReadBit(config.AnalogAddress[i].LowerErrorAddress);
  395. OilSourceStatus.OilSourceAnalogs[i].IsLowerWarn = PLCConnect.ReadBit(config.AnalogAddress[i].LowerWarnAddress);
  396. OilSourceStatus.OilSourceAnalogs[i].IsUpperError = PLCConnect.ReadBit(config.AnalogAddress[i].UpperErrorAddress);
  397. OilSourceStatus.OilSourceAnalogs[i].IsUpperWarn = PLCConnect.ReadBit(config.AnalogAddress[i].UpperWarnAddress);
  398. }
  399. Communication.GetEvent<OilSourceStatusModel>()?.Publish(this, OilSourceStatus);
  400. }
  401. }
  402. public void Stop()
  403. {
  404. OilLock.Reset();
  405. _cts?.Cancel();
  406. }
  407. }
  408. }