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<string, TaskCompletionSource<string>> _pendingTask1 = new();
|
private readonly ConcurrentDictionary<string, TaskCompletionSource<string>> _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<string> 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<AutoLineMacQueueBak>(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<AutoLineMacBarcodeQueueBak>(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<string> MESForBasketAsync(string ztype, string zlsn, string zlpn, string zstatus, string zversion, int timeoutMs = 3000)
|
{
|
var guid = Guid.NewGuid().ToString();
|
var tcs = new TaskCompletionSource<string>(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<string> 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<string>(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<string> _responseTcs1;
|
// private TaskCompletionSource<string> _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<string> 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<string> 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<string>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
// void FeedbackHandler(string raw)
|
// {
|
// try
|
// {
|
// var obj = JsonConvert.DeserializeObject<AutoLineMacQueueBak>(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<string>(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<string> 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<string>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
// void FeedbackHandler(string raw)
|
// {
|
// try
|
// {
|
// var obj = JsonConvert.DeserializeObject<AutoLineMacBarcodeQueueBak>(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<string>(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
|
{
|
/// <summary>
|
/// 唯一ID
|
/// </summary>
|
public string zbguid { get; set; } = Guid.NewGuid().ToString();
|
|
/// <summary>
|
/// 时间戳,精确到耗秒
|
/// </summary>
|
public string zdate { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff");
|
|
/// <summary>
|
/// 1:入口架子状态上报
|
///2:开始作业(3号位扫码后,开始解绑)
|
///3:出口架子状态上报
|
///4:出空篮(篮子已经停在4号位)
|
/// </summary>
|
public string ztype { get; set; }
|
|
/// <summary>
|
/// 每个ztype下对应独立一个序列号,一个业务动作一个,从0开始,
|
/// 每次加1,到达阈值后可重置(比如100后从0开始),只要和上一
|
/// 次的不一样即可
|
/// 业务动作解释:比如ztype为2时,Q01-000001解绑时传序列号1,
|
/// 如果Q01-000001在一些异常情况下,需要重试则还是传序列号为1,
|
/// 下一个Q01-000002解绑时传序列号2
|
/// 通俗的说:一个ztype+zversion只能成功处理一次(阈值重置导致
|
/// 的重复除外)
|
/// </summary>
|
public string zversion { get; set; }
|
|
/// <summary>
|
/// 目前固定NQ216(若后期扩展线需与对应线别ID一致)
|
/// </summary>
|
public string zline { get; set; }
|
|
/// <summary>
|
/// ztype为1时:DS02216
|
/// ztype为2,3,4时:DS02217(若后期扩展线需与及架子ID一致)
|
/// </summary>
|
public string zlsn { get; set; }
|
|
/// <summary>
|
/// MES只接收正确格式的数据,如Q01-000001,错误数据会返回
|
/// 999,如遇到未扫到码之类的问题,由设备重扫处理后,取到正确
|
/// 篮具码后,再上抛给MES
|
/// </summary>
|
public string zlpn { get; set; }
|
|
/// <summary>
|
/// 0:架子空闲(1号位搬到2号位完成、4号位agv已载走篮子)
|
/// 1:架子满载(1号位agv送篮已到位)
|
/// 2:预满载(表示4号位预满载,3号位开始往4号位搬时)
|
/// </summary>
|
public string zstatus { get; set; }
|
|
}
|
|
public class AutoLineMacQueueBak
|
{
|
public string zbguid { get; set; }
|
|
/// <summary>
|
/// 200:成功;999:失败
|
/// </summary>
|
public string zstatus { get; set; }
|
|
public string zerrmsg { get; set; }
|
|
/// <summary>
|
/// ztype为2解绑时,解绑成功会返回工单号,后续aoi作业时,需带上工单号上抛给mes
|
/// </summary>
|
public string zwoid { get; set; }
|
}
|
|
public class AutoLineMacBarcodeQueue
|
{
|
/// <summary>
|
/// 唯一ID
|
/// </summary>
|
public string zbguid { get; set; } = Guid.NewGuid().ToString();
|
|
/// <summary>
|
/// 时间戳,精确到耗秒
|
/// </summary>
|
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; }
|
|
/// <summary>
|
/// OK/NG
|
/// </summary>
|
public string zresult { get; set; }
|
|
/// <summary>
|
/// 标准的缺陷代码
|
/// </summary>
|
public string zreson { get; set; }
|
|
/// <summary>
|
/// 条码在当前tray中的序号
|
/// </summary>
|
public string zno { get; set; }
|
|
/// <summary>
|
/// 解绑时,mes回传的工单号
|
/// </summary>
|
public string zwoid { get; set; }
|
|
/// <summary>
|
/// 默认:N;零数尾盘:Y
|
/// </summary>
|
public string endtray { get; set; } = "N";
|
}
|
|
public class AutoLineMacBarcodeQueueBak
|
{
|
public string zbguid { get; set; }
|
|
/// <summary>
|
/// 200:成功;999:失败
|
/// </summary>
|
public string zstatus { get; set; }
|
public string zerrmsg { get; set; }
|
|
/// <summary>
|
/// tray盘标签条码
|
/// </summary>
|
public string tary_label { get; set; }
|
}
|
|
|
}
|