using Bro.Common.Helper; using Bro.M135.Common; using Bro.Process.DataBase.Models; using Microsoft.VisualBasic.Devices; using Newtonsoft.Json; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Utilities.Encoders; using RabbitMQ.Client; using RabbitMQ.Client.Events; using SourceGrid.Cells.Editors; using Sunny.UI.Win32; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Bro.M141.Process { public class RabbitMQHelper { private readonly ConnectionFactory _factory; private IConnection _connection; private IModel _sendChannel; private IModel _receiveChannel1; private IModel _receiveChannel2; private readonly ConcurrentDictionary> _pendingTask1 = new(); private readonly ConcurrentDictionary> _pendingTask2 = new(); private readonly string _queue1 = "auto_line_mac_queue_bak"; private readonly string _queue2 = "auto_line_mac_barcode_queue_bak"; public RabbitMQHelper(string host = "10.2.20.114", int port = 15672, string user = "aoiUser", string pwd = "Chia@aoi") { _factory = new ConnectionFactory { HostName = host, Port = port, UserName = user, Password = pwd, VirtualHost = "/", Ssl = new SslOption { Enabled = false }, AutomaticRecoveryEnabled = true, NetworkRecoveryInterval = TimeSpan.FromMilliseconds(5000), RequestedConnectionTimeout = TimeSpan.FromMilliseconds(3000) }; } public void Connect(int channel) { if (_connection != null && _connection.IsOpen) return; _connection = _factory.CreateConnection(); _sendChannel = _connection.CreateModel(); if (channel == 0) { _receiveChannel1 = _connection.CreateModel(); InitConsumer(_receiveChannel1, _queue1, HandleQueue1Message); } else if (channel == 1) { _receiveChannel2 = _connection.CreateModel(); InitConsumer(_receiveChannel2, _queue2, HandleQueue2Message); } else if (channel == -1) { _receiveChannel1 = _connection.CreateModel(); InitConsumer(_receiveChannel1, _queue1, HandleQueue1Message); _receiveChannel2 = _connection.CreateModel(); InitConsumer(_receiveChannel2, _queue2, HandleQueue2Message); } CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, "RabbitMQ 连接成功"); } private void InitConsumer(IModel channel, string queueName, Action handler) { channel.QueueDeclare(queueName, durable: true, exclusive: false, autoDelete: false); var consumer = new EventingBasicConsumer(channel); consumer.Received += (_, ea) => { var msg = Encoding.UTF8.GetString(ea.Body.ToArray()); CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 收到消息 [{queueName}]:{msg}"); handler?.Invoke(msg); channel.BasicAck(ea.DeliveryTag, false); }; channel.BasicConsume(queue: queueName, autoAck: false, consumer: consumer); } private void HandleQueue1Message(string message) { try { var obj = JsonConvert.DeserializeObject(message); if (obj?.zbguid != null && _pendingTask1.TryRemove(obj.zbguid, out var tcs)) { tcs.TrySetResult(message); } else { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 篮具 收到未匹配 zbguid:{obj?.zbguid}"); } } catch (Exception ex) { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"RabbitMQ 篮具 解析异常:{ex.Message}"); } } private void HandleQueue2Message(string message) { try { var obj = JsonConvert.DeserializeObject(message); if (obj?.zbguid != null && _pendingTask2.TryRemove(obj.zbguid, out var tcs)) { tcs.TrySetResult(message); } else { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 物料 收到未匹配 zbguid:{obj?.zbguid}"); } } catch (Exception ex) { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"RabbitMQ 物料 解析异常:{ex.Message}"); } } public async Task MESForBasketAsync(string ztype, string zlsn, string zlpn, string zstatus, string zversion, int timeoutMs = 3000) { var guid = Guid.NewGuid().ToString(); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _pendingTask1[guid] = tcs; var msgObj = new AutoLineMacQueue { zbguid = guid, zdate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), ztype = ztype, zversion = zversion, zline = "NQ216", zlsn = zlsn, zlpn = zlpn, zstatus = zstatus }; var message = JsonConvert.SerializeObject(msgObj); var body = Encoding.UTF8.GetBytes(message); CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 篮具 发送1:{message}"); _sendChannel.BasicPublish("", "auto_line_mac_queue", null, body); var completed = await Task.WhenAny(tcs.Task, Task.Delay(timeoutMs)); _pendingTask1.TryRemove(guid, out _); if (completed == tcs.Task) return await tcs.Task; else { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"RabbitMQ 篮具 返回超时1,zbguid={guid}"); return null; } } public async Task MESForProduceAsync(ProductModel pro, string zwoid, int znonum, string endtray = "N", string line = "NQ216", int timeoutMs = 3000) { var guid = Guid.NewGuid().ToString(); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _pendingTask2[guid] = tcs; var msgObj = new AutoLineMacBarcodeQueue { zbguid = guid, zdate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), zline = line, zbarcode = pro.SN, zresult = string.IsNullOrWhiteSpace(pro.Result) ? "NG" : pro.Result, zreson = pro.Result == "OK" ? "" : "SZ2014", zno = znonum.ToString(), zwoid = zwoid, endtray = endtray }; var message = JsonConvert.SerializeObject(msgObj); var body = Encoding.UTF8.GetBytes(message); CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ发送产品{pro.PID} 数据2:{message}"); _sendChannel.BasicPublish("", "auto_line_mac_barcode_queue", null, body); var completed = await Task.WhenAny(tcs.Task, Task.Delay(timeoutMs)); _pendingTask2.TryRemove(guid, out _); if (completed == tcs.Task) return await tcs.Task; else { CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"RabbitMQ返回超时2,PID={pro.PID}"); return null; } } public void Disconnect() { _sendChannel?.Close(); _receiveChannel1?.Close(); _receiveChannel2?.Close(); _connection?.Close(); CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 连接断开"); } } //using Bro.Common.Helper; //using Bro.M135.Common; //using Bro.Process.DataBase.Models; //using Microsoft.VisualBasic.Devices; //using Newtonsoft.Json; //using Org.BouncyCastle.Asn1.Pkcs; //using Org.BouncyCastle.Utilities.Encoders; //using RabbitMQ.Client; //using RabbitMQ.Client.Events; //using SourceGrid.Cells.Editors; //using Sunny.UI.Win32; //using System; //using System.Collections.Generic; //using System.Linq; //using System.Text; //using System.Threading.Tasks; //namespace Bro.M141.Process //{ // public class RabbitMQHelper // { // private readonly ConnectionFactory _factory; // private IConnection _connection; // private IModel _sendChannel; // private IModel _receiveChannel1; // private IModel _receiveChannel2; // private EventingBasicConsumer _consumer1; // private EventingBasicConsumer _consumer2; // private TaskCompletionSource _responseTcs1; // private TaskCompletionSource _responseTcs2; // private readonly object _lock1 = new(); // private readonly object _lock2 = new(); // private readonly string _queue1 = "auto_line_mac_queue_bak"; // private readonly string _queue2 = "auto_line_mac_barcode_queue_bak"; // public string AAzword { get; private set; } // public RabbitMQHelper(string _host = "10.2.20.114", int _port = 15672, string _user = "aoiUser", string _pwd = "Chia@aoi") // { // _factory = new ConnectionFactory // { // HostName = _host, // Port = _port, // UserName = _user, // Password = _pwd, // VirtualHost = "/", // Ssl = new SslOption { Enabled = false }, // AutomaticRecoveryEnabled = true, // NetworkRecoveryInterval = TimeSpan.FromMilliseconds(5000),//掉线5秒自动重连 // RequestedConnectionTimeout = TimeSpan.FromMilliseconds(3000)//连接超时 // }; // } // public void Connect() // { // if (_connection != null && _connection.IsOpen) return; // _connection = _factory.CreateConnection(); // _sendChannel = _connection.CreateModel(); // _receiveChannel1 = _connection.CreateModel(); // _receiveChannel2 = _connection.CreateModel(); // InitConsumer(_receiveChannel1, _queue1, HandleQueue1Message); // InitConsumer(_receiveChannel2, _queue2, HandleQueue2Message); // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ 连接成功"); // } // private void InitConsumer(IModel channel, string queueName, Action handler) // { // channel.QueueDeclare(queueName, durable: true, exclusive: false, autoDelete: false); // var consumer = new EventingBasicConsumer(channel); // consumer.Received += (model, ea) => // { // var msg = Encoding.UTF8.GetString(ea.Body.ToArray()); // handler?.Invoke(msg); // channel.BasicAck(ea.DeliveryTag, false); // }; // channel.BasicConsume(queue: queueName, autoAck: false, consumer: consumer); // } // private void HandleQueue1Message(string message) // { // lock (_lock1) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ收到1 {message}"); // _responseTcs1?.TrySetResult(message); // } // } // private void HandleQueue2Message(string message) // { // lock (_lock2) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ收到2 {message}"); // _responseTcs2?.TrySetResult(message); // } // } // public async Task MESForBasketAsync(string ztype, string zlsn, string zlpn, string zstatus, string zversion, int timeoutMs = 3000) // { // try // { // var guid = Guid.NewGuid().ToString(); // var md = new AutoLineMacQueue // { // zbguid = guid, // zdate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), // ztype = ztype, // zversion = zversion, // zline = "NQ216", // zlsn = zlsn, // zlpn = zlpn, // zstatus = zstatus // }; // var message = JsonConvert.SerializeObject(md); // var body = Encoding.UTF8.GetBytes(message); // var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // void FeedbackHandler(string raw) // { // try // { // var obj = JsonConvert.DeserializeObject(raw); // if (obj?.zbguid == guid) // { // tcs.TrySetResult(raw); // } // else // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"1不一致 发{guid} 收{obj?.zbguid}"); // } // } // catch (Exception eex) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, eex.ToString()); // } // } // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ发送1 {message}"); // lock (_lock1) // { // _responseTcs1 = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // _responseTcs1.Task.ContinueWith(t => { if (t.Result != null) FeedbackHandler(t.Result); }); // _sendChannel.BasicPublish("", "auto_line_mac_queue", null, body); // } // var completed = await Task.WhenAny(tcs.Task, Task.Delay(timeoutMs)); // return completed == tcs.Task ? await tcs.Task : null; // } // catch (Exception ee) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, ee.ToString()); // } // return null; // } // public async Task MESForproduceAsync(ProductModel pro, string zwoid, int znonum, string line = "NQ216", int timeoutMs = 3000) // { // try // { // var guid = Guid.NewGuid().ToString(); // AutoLineMacBarcodeQueue md = new AutoLineMacBarcodeQueue // { // zbguid = guid, // zdate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), // zline = line, // zbarcode = pro.SN, // zresult = pro.Result == "" ? "NG" : pro.Result, // zreson = pro.Result == "OK" ? "" : "SZ2014", // zno = znonum.ToString(), // //zno = "1", // zwoid = zwoid, // endtray = "N", // //endtray = "Y" // }; // string message = JsonConvert.SerializeObject(md); // var body = Encoding.UTF8.GetBytes(message); // var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // void FeedbackHandler(string raw) // { // try // { // var obj = JsonConvert.DeserializeObject(raw); // if (obj?.zbguid == guid) // { // tcs.TrySetResult(raw); // } // else // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"2不一致 发{guid} 收{obj?.zbguid}"); // } // } // catch (Exception eex) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, eex.ToString()); // } // } // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"RabbitMQ发送产品{pro.PID}数据2 {message}"); // lock (_lock2) // { // _responseTcs2 = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // _responseTcs2.Task.ContinueWith(t => { if (t.Result != null) FeedbackHandler(t.Result); }); // _sendChannel.BasicPublish("", "auto_line_mac_barcode_queue", null, body); // } // var completed = await Task.WhenAny(tcs.Task, Task.Delay(timeoutMs)); // return completed == tcs.Task ? await tcs.Task : null; // } // catch (Exception ee) // { // CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, ee.ToString()); // } // return null; // } // public void Disconnect() // { // _sendChannel?.Close(); // _receiveChannel1?.Close(); // _receiveChannel2?.Close(); // _connection?.Close(); // } // } public class AutoLineMacQueue { /// /// 唯一ID /// public string zbguid { get; set; } = Guid.NewGuid().ToString(); /// /// 时间戳,精确到耗秒 /// public string zdate { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"); /// /// 1:入口架子状态上报 ///2:开始作业(3号位扫码后,开始解绑) ///3:出口架子状态上报 ///4:出空篮(篮子已经停在4号位) /// public string ztype { get; set; } /// /// 每个ztype下对应独立一个序列号,一个业务动作一个,从0开始, /// 每次加1,到达阈值后可重置(比如100后从0开始),只要和上一 /// 次的不一样即可 /// 业务动作解释:比如ztype为2时,Q01-000001解绑时传序列号1, /// 如果Q01-000001在一些异常情况下,需要重试则还是传序列号为1, /// 下一个Q01-000002解绑时传序列号2 /// 通俗的说:一个ztype+zversion只能成功处理一次(阈值重置导致 /// 的重复除外) /// public string zversion { get; set; } /// /// 目前固定NQ216(若后期扩展线需与对应线别ID一致) /// public string zline { get; set; } /// /// ztype为1时:DS02216 /// ztype为2,3,4时:DS02217(若后期扩展线需与及架子ID一致) /// public string zlsn { get; set; } /// /// MES只接收正确格式的数据,如Q01-000001,错误数据会返回 /// 999,如遇到未扫到码之类的问题,由设备重扫处理后,取到正确 /// 篮具码后,再上抛给MES /// public string zlpn { get; set; } /// /// 0:架子空闲(1号位搬到2号位完成、4号位agv已载走篮子) /// 1:架子满载(1号位agv送篮已到位) /// 2:预满载(表示4号位预满载,3号位开始往4号位搬时) /// public string zstatus { get; set; } } public class AutoLineMacQueueBak { public string zbguid { get; set; } /// /// 200:成功;999:失败 /// public string zstatus { get; set; } public string zerrmsg { get; set; } /// /// ztype为2解绑时,解绑成功会返回工单号,后续aoi作业时,需带上工单号上抛给mes /// public string zwoid { get; set; } } public class AutoLineMacBarcodeQueue { /// /// 唯一ID /// public string zbguid { get; set; } = Guid.NewGuid().ToString(); /// /// 时间戳,精确到耗秒 /// public string zdate { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"); public string zline { get; set; } public string zbarcode { get; set; } /// /// OK/NG /// public string zresult { get; set; } /// /// 标准的缺陷代码 /// public string zreson { get; set; } /// /// 条码在当前tray中的序号 /// public string zno { get; set; } /// /// 解绑时,mes回传的工单号 /// public string zwoid { get; set; } /// /// 默认:N;零数尾盘:Y /// public string endtray { get; set; } = "N"; } public class AutoLineMacBarcodeQueueBak { public string zbguid { get; set; } /// /// 200:成功;999:失败 /// public string zstatus { get; set; } public string zerrmsg { get; set; } /// /// tray盘标签条码 /// public string tary_label { get; set; } } }