Compare commits
4 Commits
a4d411bcb7
...
14b49d38a2
Author | SHA1 | Date |
---|---|---|
huangxianguo | 14b49d38a2 | |
huangxianguo | 2bdf58a0c8 | |
huangxianguo | eb4e1b69de | |
huangxianguo | 35033aa980 |
|
@ -8,7 +8,10 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" />
|
<PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="7.0.15" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||||
|
<PackageReference Include="Quartz" Version="3.10.0" />
|
||||||
|
<PackageReference Include="sqlite-net-sqlcipher" Version="1.9.172" />
|
||||||
<PackageReference Include="System.Management" Version="8.0.0"/>
|
<PackageReference Include="System.Management" Version="8.0.0"/>
|
||||||
<PackageReference Include="Serilog" Version="4.0.0"/>
|
<PackageReference Include="Serilog" Version="4.0.0"/>
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972"/>
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972"/>
|
||||||
|
@ -36,4 +39,8 @@
|
||||||
<None Remove=".gitignore" />
|
<None Remove=".gitignore" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Service\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
public enum ChipColorEnum
|
||||||
|
{
|
||||||
|
R = 1,
|
||||||
|
G = 2,
|
||||||
|
B = 3
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库实体的父类
|
||||||
|
/// </summary>
|
||||||
|
public class Entity
|
||||||
|
{
|
||||||
|
[PrimaryKey] public string? Id { get; set; }
|
||||||
|
|
||||||
|
[Column("create_time")] public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
|
[Column("update_time")] public DateTime UpdateTime { get; set; } = DateTime.Now;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 日志参数
|
||||||
|
/// </summary>
|
||||||
|
[Table("log_params")]
|
||||||
|
[Description("日志参数")]
|
||||||
|
public class LogParams : Entity
|
||||||
|
{
|
||||||
|
[Column("level"), Description("日志级别")] public string? Level { get; set; }
|
||||||
|
|
||||||
|
[Column("path"), Description("日志存放路径")]
|
||||||
|
public string? Path { get; set; }
|
||||||
|
|
||||||
|
[Column("upload_corn"), Description("日志上传时间")]
|
||||||
|
public string? UploadCorn { get; set; }
|
||||||
|
|
||||||
|
[Column("upload_levels"), Description("日志上传级别")]
|
||||||
|
public string? UploadLevels { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
[Table("message_failure_record"), Description("消息发送失败记录")]
|
||||||
|
public class MessageFailureRecord : Entity
|
||||||
|
{
|
||||||
|
[Column("topic"), Description("主题")] public string Topic { get; set; }
|
||||||
|
|
||||||
|
[Column("payload"), Description("消息内容")]
|
||||||
|
public string Payload { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using MasstransferCommon.Model.Enum;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基板信息
|
||||||
|
/// </summary>
|
||||||
|
[Table("substrates")]
|
||||||
|
public class Substrate : Entity
|
||||||
|
{
|
||||||
|
[Column("context_id"), Description("上下文ID")]
|
||||||
|
public string? ContextId { get; set; }
|
||||||
|
|
||||||
|
[Column("substrate_code"), Description("基板编号")]
|
||||||
|
public string SubstrateCode { get; set; }
|
||||||
|
|
||||||
|
[Column("jig_code"), Description("治具编号")]
|
||||||
|
public string JigCode { get; set; }
|
||||||
|
|
||||||
|
[Column("substrate_type"), Description("基板类型")]
|
||||||
|
public SubstrateTypeEnum SubstrateType { get; set; }
|
||||||
|
|
||||||
|
[Column("row"), Description("基板行")] public int Row { get; set; }
|
||||||
|
|
||||||
|
[Column("column"), Description("基板列")] public int Column { get; set; }
|
||||||
|
|
||||||
|
[Column("batch_no"), Description("批次号")]
|
||||||
|
public string BatchNo { get; set; }
|
||||||
|
|
||||||
|
[Column("formula_id"), Description("配方ID")]
|
||||||
|
public string FormulaId { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
[Table("wafers"), Description("晶环信息")]
|
||||||
|
public class Wafer : Entity
|
||||||
|
{
|
||||||
|
[Column("wafer_code"), Description("晶片编号")]
|
||||||
|
public string? WaferCode { get; set; }
|
||||||
|
|
||||||
|
[Column("color"), Description("晶片颜色")] public ChipColorEnum Color { get; set; }
|
||||||
|
|
||||||
|
[Column("context_id"), Description("上下文id")]
|
||||||
|
public string? ContextId { get; set; }
|
||||||
|
|
||||||
|
[Column("column"), Description("列")] public int Column { get; set; }
|
||||||
|
|
||||||
|
[Column("row"), Description("行")] public int Row { get; set; }
|
||||||
|
|
||||||
|
[Column("used"), Description("是否已使用")] public bool Used { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
[Table("wafer_used_record"), Description("晶环使用记录")]
|
||||||
|
public class WaferUsedRecord : Entity
|
||||||
|
{
|
||||||
|
[Column("context_id"), Description("上下文编号")]
|
||||||
|
public string? ContextId { get; set; }
|
||||||
|
|
||||||
|
[Column("wafer_code"), Description("晶环编号")]
|
||||||
|
public string? WaferCode { get; set; }
|
||||||
|
|
||||||
|
[Column("substrate_code"), Description("基板编号")]
|
||||||
|
public string? SubstrateCode { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace MasstransferCommon.Model.Enum;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 防止注册表被恶意篡改,这里的注册许可类型需要做一些混淆
|
||||||
|
/// </summary>
|
||||||
|
public enum LicenseTypeEnum
|
||||||
|
{
|
||||||
|
// 临时许可
|
||||||
|
Temporary = unchecked(int.MaxValue - 123456),
|
||||||
|
|
||||||
|
// 正式许可
|
||||||
|
Formal = unchecked(int.MaxValue - 123457)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace MasstransferCommon.Model.Enum;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 锁定状态
|
||||||
|
/// </summary>
|
||||||
|
public enum LockStateEnum
|
||||||
|
{
|
||||||
|
// 锁定状态
|
||||||
|
LockedState = int.MaxValue / 3,
|
||||||
|
|
||||||
|
// 等待锁定状态
|
||||||
|
WaitToLockedState = int.MaxValue / 4,
|
||||||
|
|
||||||
|
// 解锁状态
|
||||||
|
UnLockedState = int.MaxValue / 5,
|
||||||
|
|
||||||
|
// 等待解锁状态
|
||||||
|
WaitToUnLockedState = int.MaxValue / 6
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Enum;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基材类型
|
||||||
|
/// </summary>
|
||||||
|
public enum SubstrateTypeEnum
|
||||||
|
{
|
||||||
|
[Description("PCB")] PCB = 1,
|
||||||
|
[Description("玻璃")] Glass = 2
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Impl;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.scheduler;
|
||||||
|
|
||||||
|
public class SchedulerHelper
|
||||||
|
{
|
||||||
|
private static readonly Lazy<IScheduler> lazyScheduler = new(() => InitSchedulerAsync().GetAwaiter().GetResult());
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, IJobDetail> _jobDetails = new();
|
||||||
|
|
||||||
|
private static IScheduler Scheduler => lazyScheduler.Value;
|
||||||
|
|
||||||
|
private static async Task<IScheduler> InitSchedulerAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await new StdSchedulerFactory().GetScheduler();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error($"Failed to initialize scheduler: {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Start()
|
||||||
|
{
|
||||||
|
await Scheduler.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task SchedulerInterval<T>(Dictionary<string, object>? data, int interval,
|
||||||
|
string group = "defaultGroup") where T : IJob
|
||||||
|
{
|
||||||
|
var job = CreateJob<T>(data, group);
|
||||||
|
|
||||||
|
var trigger = TriggerBuilder.Create()
|
||||||
|
.WithIdentity(typeof(T).Name, group)
|
||||||
|
.StartNow()
|
||||||
|
.WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever())
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await Scheduler.ScheduleJob(job, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task SchedulerCorn<T>(Dictionary<string, object>? data, string? cronExpression,
|
||||||
|
string group = "defaultGroup") where T : IJob
|
||||||
|
{
|
||||||
|
var job = CreateJob<T>(data, group);
|
||||||
|
|
||||||
|
var trigger = TriggerBuilder.Create()
|
||||||
|
.WithIdentity(typeof(T).Name, group)
|
||||||
|
.StartNow()
|
||||||
|
.WithSchedule(CronScheduleBuilder.CronSchedule(cronExpression))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await Scheduler.ScheduleJob(job, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IJobDetail CreateJob<T>(Dictionary<string, object>? data, string group) where T : IJob
|
||||||
|
{
|
||||||
|
if (_jobDetails.ContainsKey(typeof(T).Name)) return _jobDetails[typeof(T).Name];
|
||||||
|
|
||||||
|
var job = JobBuilder.Create<T>()
|
||||||
|
.WithIdentity(typeof(T).Name, group)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
if (data != null && data.Count > 0)
|
||||||
|
foreach (var item in data)
|
||||||
|
job.JobDataMap.Add(item.Key, item.Value);
|
||||||
|
|
||||||
|
_jobDetails[typeof(T).Name] = job;
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task PauseJob<T>(string group = "defaultGroup")
|
||||||
|
{
|
||||||
|
if (_jobDetails.ContainsKey(typeof(T).Name)) await Scheduler.PauseJob(JobKey.Create(typeof(T).Name, group));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ResumeJob<T>(string group = "defaultGroup")
|
||||||
|
{
|
||||||
|
if (_jobDetails.ContainsKey(typeof(T).Name)) await Scheduler.ResumeJob(JobKey.Create(typeof(T).Name, group));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Shutdown()
|
||||||
|
{
|
||||||
|
if (!Scheduler.IsShutdown) await Scheduler.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task TriggerOnceImmediately<T>(string group = "defaultGroup") where T : IJob
|
||||||
|
{
|
||||||
|
if (!_jobDetails.ContainsKey(typeof(T).Name)) return;
|
||||||
|
|
||||||
|
await Scheduler.TriggerJob(new JobKey(typeof(T).Name, group));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace MasstransferExporter.DataExporter.Model;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动打记录
|
||||||
|
/// 每次基板动打完成后进行触发上传
|
||||||
|
/// </summary>
|
||||||
|
public class StrikeRecord
|
||||||
|
{
|
||||||
|
public string BatchNumber { get; set; }
|
||||||
|
public string PcbNumber { get; set; }
|
||||||
|
public string ChipType { get; set; }
|
||||||
|
public string HitQuantity { get; set; }
|
||||||
|
public string PcbInputTimeCost { get; set; }
|
||||||
|
public string PcbScanTimeCost { get; set; }
|
||||||
|
public string PcbOutputTimeCost { get; set; }
|
||||||
|
public List<StrikeWaferRecord> Rounds { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace MasstransferExporter.DataExporter.Model;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每次动打期间用到的wafer记录
|
||||||
|
/// </summary>
|
||||||
|
public class StrikeWaferRecord
|
||||||
|
{
|
||||||
|
public string WaferNumber { get; set; }
|
||||||
|
public string ChipQuantity { get; set; }
|
||||||
|
public string WaferInputTimeCost { get; set; }
|
||||||
|
public string ChipScanTimeCost { get; set; }
|
||||||
|
public string ProdutionTimeCost { get; set; }
|
||||||
|
public string PcbCheckTimeCost { get; set; }
|
||||||
|
public string WaferOutputTimeCost { get; set; }
|
||||||
|
public string HitedQuantity { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace MasstransferExporter.DataExporter;
|
||||||
|
|
||||||
|
public class StrikeRecordService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 上报动打记录
|
||||||
|
/// </summary>
|
||||||
|
private static void ReportStrikeRecord()
|
||||||
|
{
|
||||||
|
// 根据这个基板编号,从记录中找到所有的跟基板有关的生产记录
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace MasstransferExporter.LogExporter;
|
||||||
|
|
||||||
|
public class LogFileExporter
|
||||||
|
{
|
||||||
|
public async Task Export(string logFilePath)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,4 +34,8 @@
|
||||||
<None Remove="obj\**" />
|
<None Remove="obj\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="ImageExporter\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
class Program
|
using MasstransferExporter.RemoteControl;
|
||||||
|
using MasstransferExporter.RemoteControl.Model;
|
||||||
|
|
||||||
|
class Program
|
||||||
{
|
{
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
|
Thread.Sleep(30000);
|
||||||
|
|
||||||
|
var cmd = new LockCmd
|
||||||
|
{
|
||||||
|
Action = 1,
|
||||||
|
ExpiryTime = 0,
|
||||||
|
LockType = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
RemoteLockService.HandleLockCmd(cmd);
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("按任意键退出");
|
Console.WriteLine("按任意键退出");
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
namespace MasstransferExporter.RemoteControl.Model;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 锁机指令
|
||||||
|
/// </summary>
|
||||||
|
public class LockCmd
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 0 锁机 1 解锁
|
||||||
|
/// </summary>
|
||||||
|
public int Action { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 0 立即执行
|
||||||
|
/// 1 到期执行
|
||||||
|
/// </summary>
|
||||||
|
public int LockType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 到期时间
|
||||||
|
/// </summary>
|
||||||
|
public long ExpiryTime { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using MasstransferCommon.Model.Enum;
|
||||||
|
using MasstransferCommon.Utils;
|
||||||
|
using MasstransferExporter.RemoteControl.Model;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MasstransferExporter.RemoteControl;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 远程锁定服务
|
||||||
|
/// </summary>
|
||||||
|
public class RemoteLockService
|
||||||
|
{
|
||||||
|
private const string KeyPath = @"Software\Masstransfer\Security";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理接收到锁机业务指令
|
||||||
|
/// </summary>
|
||||||
|
public static void HandleLockCmd(LockCmd cmd)
|
||||||
|
{
|
||||||
|
var action = cmd.Action;
|
||||||
|
|
||||||
|
if (action == 0)
|
||||||
|
{
|
||||||
|
// 更新注册表锁机状态
|
||||||
|
var lockType = cmd.LockType;
|
||||||
|
if (lockType == 0)
|
||||||
|
{
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "LockState", LockStateEnum.LockedState, RegistryValueKind.DWord);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "LockState", LockStateEnum.WaitToLockedState,
|
||||||
|
RegistryValueKind.DWord);
|
||||||
|
// 写入超时的时间
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "ExpireTime", cmd.ExpiryTime, RegistryValueKind.DWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 解锁
|
||||||
|
var lockType = cmd.LockType;
|
||||||
|
if (lockType == 0)
|
||||||
|
{
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "LockState", LockStateEnum.UnLockedState,
|
||||||
|
RegistryValueKind.DWord);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "LockState", LockStateEnum.WaitToUnLockedState,
|
||||||
|
RegistryValueKind.DWord);
|
||||||
|
// 写入等待解锁超时的时间
|
||||||
|
RegistryHelper.WriteValue(KeyPath, "ExpireTime", cmd.ExpiryTime, RegistryValueKind.DWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,11 @@ public class SqliteHelper
|
||||||
private const string Password = "88888888";
|
private const string Password = "88888888";
|
||||||
private readonly SQLiteConnection _db;
|
private readonly SQLiteConnection _db;
|
||||||
|
|
||||||
public SqliteHelper()
|
private static SqliteHelper? _instance;
|
||||||
|
|
||||||
|
private static readonly object Locker = new();
|
||||||
|
|
||||||
|
private SqliteHelper()
|
||||||
{
|
{
|
||||||
var profile = Environment.GetEnvironmentVariable("USERPROFILE");
|
var profile = Environment.GetEnvironmentVariable("USERPROFILE");
|
||||||
var path = Path.Combine(profile, "masstransfer", "mass-transfer.db");
|
var path = Path.Combine(profile, "masstransfer", "mass-transfer.db");
|
||||||
|
@ -34,6 +38,17 @@ public class SqliteHelper
|
||||||
_db.Execute($"PRAGMA key = '{Password}'");
|
_db.Execute($"PRAGMA key = '{Password}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SqliteHelper GetInstance()
|
||||||
|
{
|
||||||
|
lock (Locker)
|
||||||
|
{
|
||||||
|
// 如果类的实例不存在则创建,否则直接返回
|
||||||
|
_instance ??= new SqliteHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 插入数据
|
/// 插入数据
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Reflection;
|
using MasstransferCommon.Model.Entity;
|
||||||
using MasstransferCommon.Utils;
|
using MasstransferCommon.Utils;
|
||||||
|
using MasstransferInfrastructure.Database.Sqlite;
|
||||||
using MasstransferInfrastructure.Mqtt.Model;
|
using MasstransferInfrastructure.Mqtt.Model;
|
||||||
using MQTTnet;
|
using MQTTnet;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
|
@ -10,6 +11,8 @@ namespace MasstransferInfrastructure.Mqtt.Client;
|
||||||
|
|
||||||
public class MessageQueueHelper
|
public class MessageQueueHelper
|
||||||
{
|
{
|
||||||
|
private static readonly SqliteHelper Helper = SqliteHelper.GetInstance();
|
||||||
|
|
||||||
private static readonly Dictionary<string, List<Delegate>> Subscribers = new();
|
private static readonly Dictionary<string, List<Delegate>> Subscribers = new();
|
||||||
|
|
||||||
private static readonly MqttClient Client = new();
|
private static readonly MqttClient Client = new();
|
||||||
|
@ -63,7 +66,29 @@ public class MessageQueueHelper
|
||||||
public static async Task<bool> Publish(string topic, object message,
|
public static async Task<bool> Publish(string topic, object message,
|
||||||
MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtMostOnce)
|
MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
{
|
{
|
||||||
return await Client.Publish(topic, message, qos);
|
try
|
||||||
|
{
|
||||||
|
var isSuccess = await Client.Publish(topic, message, qos);
|
||||||
|
if (!isSuccess)
|
||||||
|
{
|
||||||
|
throw new Exception("发送消息失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
MessageFailureRecord record = new()
|
||||||
|
{
|
||||||
|
Payload = JsonUtil.ToJson(message),
|
||||||
|
Topic = topic
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将当前消息记录到数据库
|
||||||
|
Helper.Insert(record);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -87,7 +112,7 @@ public class MessageQueueHelper
|
||||||
var methodInfo = subscriber.Method;
|
var methodInfo = subscriber.Method;
|
||||||
var parameters = methodInfo.GetParameters();
|
var parameters = methodInfo.GetParameters();
|
||||||
if (parameters.Length != 2) continue;
|
if (parameters.Length != 2) continue;
|
||||||
var type = parameters[1].ParameterType;
|
var type = parameters[1].ParameterType;
|
||||||
// 通知订阅者
|
// 通知订阅者
|
||||||
subscriber.DynamicInvoke(topic, JsonUtil.FromJson(type, message));
|
subscriber.DynamicInvoke(topic, JsonUtil.FromJson(type, message));
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,12 +108,13 @@ class MqttClient
|
||||||
|
|
||||||
var payload = message as string ?? JsonUtil.ToJson(message);
|
var payload = message as string ?? JsonUtil.ToJson(message);
|
||||||
|
|
||||||
await _client.PublishAsync(new MqttApplicationMessageBuilder()
|
var result = await _client.PublishAsync(new MqttApplicationMessageBuilder()
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(payload)
|
.WithPayload(payload)
|
||||||
.WithQualityOfServiceLevel(qos)
|
.WithQualityOfServiceLevel(qos)
|
||||||
.Build());
|
.Build());
|
||||||
return true;
|
|
||||||
|
return result.IsSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in New Issue