mqtt初版
This commit is contained in:
parent
cfdcd5d6bf
commit
5712801344
@ -19,25 +19,70 @@ namespace DOAN.Model.MES.recipe.Dto
|
||||
/// </summary>
|
||||
public class PfRecipeIssueLogDto
|
||||
{
|
||||
public string Receiver { get; set; }
|
||||
/// <summary>
|
||||
/// 下达记录ID(主键)
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 配方码
|
||||
/// </summary>
|
||||
public string RecipeCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本编号
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下达时间
|
||||
/// </summary>
|
||||
|
||||
public DateTime? IssueTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 工单号
|
||||
/// </summary>
|
||||
|
||||
public string Workorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品码
|
||||
/// </summary>
|
||||
|
||||
public string ProductCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品名称
|
||||
/// </summary>
|
||||
|
||||
public string ProductName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建人
|
||||
/// </summary>
|
||||
|
||||
public string CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
|
||||
public DateTime? CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新人
|
||||
/// </summary>
|
||||
|
||||
public string UpdatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
|
||||
public DateTime? UpdatedTime { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
public string RecipeCode { get; set; }
|
||||
|
||||
public string Version { get; set; }
|
||||
|
||||
public DateTime? IssueTime { get; set; }
|
||||
|
||||
public string IssuedBy { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@ -7,10 +7,50 @@ namespace DOAN.Model.MES.recipe
|
||||
[SugarTable("pf_recipe_issue_log")]
|
||||
public class PfRecipeIssueLog
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 接收方
|
||||
/// 下达记录ID(主键)
|
||||
/// </summary>
|
||||
public string Receiver { get; set; }
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 配方码
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "recipe_code")]
|
||||
public string RecipeCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本编号
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下达时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "issue_time")]
|
||||
public DateTime? IssueTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 工单号
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "workorder")]
|
||||
public string Workorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品码
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "productcode")]
|
||||
public string ProductCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品名称
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "productname")]
|
||||
public string ProductName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建人
|
||||
@ -36,34 +76,5 @@ namespace DOAN.Model.MES.recipe
|
||||
[SugarColumn(ColumnName = "updated_time")]
|
||||
public DateTime? UpdatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下达记录ID(主键)
|
||||
/// </summary>
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 配方码
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "recipe_code")]
|
||||
public string RecipeCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本编号
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下达时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "issue_time")]
|
||||
public DateTime? IssueTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下达人
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "issued_by")]
|
||||
public string IssuedBy { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,6 @@ public interface IPADReportWorkService
|
||||
|
||||
|
||||
int UpdateProReportwork(ProReportwork parm);
|
||||
int StartWorkOrder(string workorder);
|
||||
Task<int> StartWorkOrder(string workorder);
|
||||
int FinishWorkOrder(string workorder);
|
||||
}
|
||||
@ -1,8 +1,10 @@
|
||||
using DOAN.Infrastructure.Helper;
|
||||
using DOAN.Model;
|
||||
using DOAN.Model.MES.base_;
|
||||
using DOAN.Model.MES.mm;
|
||||
using DOAN.Model.MES.product;
|
||||
using DOAN.Model.MES.product.Dto;
|
||||
using DOAN.Model.MES.recipe;
|
||||
using DOAN.Repository;
|
||||
using DOAN.Service.MES.mm.line;
|
||||
using DOAN.Service.Mobile.IService;
|
||||
@ -162,7 +164,7 @@ namespace DOAN.Service.Mobile
|
||||
return Update(model, true);
|
||||
}
|
||||
|
||||
public int StartWorkOrder(string workorder)
|
||||
public async Task<int> StartWorkOrder(string workorder)
|
||||
{
|
||||
var result = 0;
|
||||
// 获取同一天 同一组 同一线 的所有工单 把状态2 设为init 1
|
||||
@ -184,9 +186,53 @@ namespace DOAN.Service.Mobile
|
||||
});
|
||||
|
||||
//TODO 拼接MQTT消息,发送给设备,工单信息和配方信息
|
||||
Context.Queryable<Pfref>
|
||||
var RecipeMesg= Context.Queryable<PfRefProductRecipe>().LeftJoin<PfRecipeVersion>((rpr, r) => rpr.RecipeCode == r.RecipeCode)
|
||||
.Where((rpr, r) => rpr.Productcode == handleWorkorder.ProductionCode)
|
||||
.Where((rpr, r) => r.Status == 1)
|
||||
.Select((rpr, r) => new
|
||||
{
|
||||
RecipeCode = r.RecipeCode,
|
||||
Version = r.Version,
|
||||
ParamList = Context.Queryable<PfRecipeParameters>().Where(it => it.RecipeCode == r.RecipeCode && it.Version == r.Version).ToList()
|
||||
}).First();
|
||||
if( RecipeMesg==null)
|
||||
{
|
||||
throw new Exception("未找到对应的配方信息,请检查产品与配方的关联关系,或配方状态是否有效");
|
||||
}
|
||||
|
||||
// 合并两个对象为匿名对象
|
||||
var combinedObject = new
|
||||
{
|
||||
WorkorderInfo = handleWorkorder,
|
||||
RecipeInfo = RecipeMesg
|
||||
};
|
||||
|
||||
|
||||
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(combinedObject, Newtonsoft.Json.Formatting.Indented);
|
||||
//插入配方派发日志
|
||||
PfRecipeIssueLog pfRecipeIssueLog = new PfRecipeIssueLog();
|
||||
pfRecipeIssueLog.RecipeCode = RecipeMesg.RecipeCode;
|
||||
pfRecipeIssueLog.Version = RecipeMesg.Version;
|
||||
pfRecipeIssueLog.IssueTime = DateTime.Now;
|
||||
pfRecipeIssueLog.Workorder = handleWorkorder.Workorder;
|
||||
pfRecipeIssueLog.ProductCode = handleWorkorder.ProductionCode;
|
||||
pfRecipeIssueLog.ProductName = handleWorkorder.ProductionName;
|
||||
pfRecipeIssueLog.CreatedBy = "PDA";
|
||||
pfRecipeIssueLog.CreatedTime = DateTime.Now;
|
||||
Context.Insertable(pfRecipeIssueLog).ExecuteCommand();
|
||||
|
||||
|
||||
MqttHelper _mqttHelper=new MqttHelper("mqtt://192.168.50.163", 8883);
|
||||
|
||||
// 连接
|
||||
await _mqttHelper.ConnectAsync();
|
||||
|
||||
// 发送多条消息
|
||||
|
||||
await _mqttHelper.PublishMessageAsync("MES/Workorder/Start", jsonString);
|
||||
|
||||
// 断开连接
|
||||
await _mqttHelper.DisconnectAsync();
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
<PackageReference Include="AspectCore.Abstractions" Version="2.4.0" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.0" />
|
||||
<PackageReference Include="MQTTnet" Version="5.0.1.1416" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
|
||||
169
Infrastructure/Helper/MqttHelper.cs
Normal file
169
Infrastructure/Helper/MqttHelper.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using MQTTnet;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
namespace DOAN.Infrastructure.Helper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// MQTT 消息发送工具类
|
||||
/// </summary>
|
||||
public class MqttHelper : IDisposable
|
||||
{
|
||||
// MQTT Broker 配置(可外部设置或配置文件读取)
|
||||
public string MqttBrokerUrl { get; set; } = "broker.hivemq.com";
|
||||
public int MqttBrokerPort { get; set; } = 1883;
|
||||
public string MqttUsername { get; set; } = null;
|
||||
public string MqttPassword { get; set; } = null;
|
||||
|
||||
private IMqttClient _mqttClient;
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数 - 使用默认配置
|
||||
/// </summary>
|
||||
public MqttHelper() { }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数 - 自定义配置
|
||||
/// </summary>
|
||||
public MqttHelper(string brokerUrl, int brokerPort, string username = null, string password = null)
|
||||
{
|
||||
MqttBrokerUrl = brokerUrl;
|
||||
MqttBrokerPort = brokerPort;
|
||||
MqttUsername = username;
|
||||
MqttPassword = password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接到 MQTT Broker
|
||||
/// </summary>
|
||||
public async Task<bool> ConnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mqttClient?.IsConnected == true)
|
||||
{
|
||||
Console.WriteLine("MQTT 客户端已经连接");
|
||||
return true;
|
||||
}
|
||||
|
||||
var factory = new MqttClientFactory();
|
||||
_mqttClient = factory.CreateMqttClient();
|
||||
|
||||
var options = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer(MqttBrokerUrl, MqttBrokerPort)
|
||||
.WithCredentials(MqttUsername, MqttPassword)
|
||||
.WithCleanSession()
|
||||
.Build();
|
||||
|
||||
Console.WriteLine($"正在连接到 MQTT Broker: {MqttBrokerUrl}:{MqttBrokerPort}...");
|
||||
await _mqttClient.ConnectAsync(options);
|
||||
|
||||
Console.WriteLine("✅ MQTT 连接成功!");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ MQTT 连接失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息到指定主题
|
||||
/// </summary>
|
||||
/// <param name="topic">目标主题</param>
|
||||
/// <param name="messageContent">消息内容</param>
|
||||
/// <param name="qosLevel">QoS 级别,默认为 AtLeastOnce(1)</param>
|
||||
/// <param name="retain">是否保留消息,默认为 false</param>
|
||||
public async Task<bool> PublishMessageAsync(string topic, string messageContent,
|
||||
MqttQualityOfServiceLevel qosLevel = MqttQualityOfServiceLevel.AtLeastOnce,
|
||||
bool retain = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mqttClient?.IsConnected != true)
|
||||
{
|
||||
Console.WriteLine("MQTT 客户端未连接,尝试重新连接...");
|
||||
if (!await ConnectAsync())
|
||||
{
|
||||
Console.WriteLine("❌ 重连失败,无法发送消息");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var message = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic)
|
||||
.WithPayload(messageContent)
|
||||
.WithQualityOfServiceLevel(qosLevel)
|
||||
.WithRetainFlag(retain)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine($"正在向主题 '{topic}' 发送消息: {messageContent}");
|
||||
await _mqttClient.PublishAsync(message);
|
||||
|
||||
Console.WriteLine("✅ 消息发送成功!");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ 消息发送失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息(使用默认主题配置)
|
||||
/// </summary>
|
||||
/// <param name="messageContent">消息内容</param>
|
||||
/// <param name="qosLevel">QoS 级别</param>
|
||||
/// <param name="retain">是否保留消息</param>
|
||||
public async Task<bool> PublishMessageAsync(string messageContent,
|
||||
MqttQualityOfServiceLevel qosLevel = MqttQualityOfServiceLevel.AtLeastOnce,
|
||||
bool retain = false)
|
||||
{
|
||||
return await PublishMessageAsync("product/topic", messageContent, qosLevel, retain);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开 MQTT 连接
|
||||
/// </summary>
|
||||
public async Task DisconnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_mqttClient?.IsConnected == true)
|
||||
{
|
||||
await _mqttClient.DisconnectAsync();
|
||||
Console.WriteLine("🔌 MQTT 已断开连接");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ 断开连接时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否已连接
|
||||
/// </summary>
|
||||
public bool IsConnected => _mqttClient?.IsConnected == true;
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
DisconnectAsync().Wait();
|
||||
_mqttClient?.Dispose();
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user