修复提交
This commit is contained in:
272
linesider_screen_tool/Hepler/BartenderPrintingTool.cs
Normal file
272
linesider_screen_tool/Hepler/BartenderPrintingTool.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BarTender;
|
||||
namespace linesider_screen_tool
|
||||
{
|
||||
public class BartenderPrintHelper : IDisposable
|
||||
{
|
||||
private Application _btApp;
|
||||
private Format _btFormat;
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 Bartender 应用程序
|
||||
/// </summary>
|
||||
public BartenderPrintHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
_btApp = new Application();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("无法初始化 Bartender 应用程序。请确保 BarTender 已安装。", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打印标签
|
||||
/// </summary>
|
||||
/// <param name="templatePath">标签模板路径</param>
|
||||
/// <param name="subStringValues">标签变量键值对</param>
|
||||
/// <param name="copies">打印份数</param>
|
||||
/// <param name="serializedLabels">序列化标签数量</param>
|
||||
/// <returns>是否打印成功</returns>
|
||||
public bool PrintLabel(string templatePath, Dictionary<string, string> subStringValues, int copies = 1, int serializedLabels = 1)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("BartenderPrintHelper", "对象已被释放,不能执行打印操作。");
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
Console.WriteLine("正在启动 BarTender...");
|
||||
|
||||
// 2. 创建 BarTender 应用实例
|
||||
var btApp = new Application();
|
||||
|
||||
// 3. 设置可见性(调试时建议开启)
|
||||
// btApp.Visible = false; // 设置为 true 可以看到 BarTender 界面
|
||||
Console.WriteLine("BarTender 启动成功!");
|
||||
|
||||
// 4. 打开模板文件
|
||||
Console.WriteLine($"正在打开模板: {templatePath}");
|
||||
Format btFormat = btApp.Formats.Open(templatePath);
|
||||
|
||||
Console.WriteLine("模板加载成功!");
|
||||
|
||||
// 5. 设置打印份数
|
||||
btFormat.PrintSetup.NumberSerializedLabels = 1;
|
||||
// 6. 设置变量值(添加日志输出)
|
||||
Console.WriteLine("正在设置变量值...");
|
||||
foreach (var a in subStringValues)
|
||||
{
|
||||
btFormat.SetNamedSubStringValue(a.Key, a.Value);
|
||||
}
|
||||
// 8. 执行打印
|
||||
Console.WriteLine("正在发送打印任务...");
|
||||
btFormat.PrintOut(false, false); // 不显示对话框,不等待打印完成
|
||||
Console.WriteLine("打印任务已发送!");
|
||||
|
||||
// 9. 关闭模板
|
||||
btFormat.Close(BtSaveOptions.btDoNotSaveChanges);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// 清理托管资源
|
||||
}
|
||||
|
||||
// 清理非托管资源
|
||||
if (_btFormat != null)
|
||||
{
|
||||
_btFormat.Close(BtSaveOptions.btDoNotSaveChanges);
|
||||
System.Runtime.InteropServices.Marshal.ReleaseComObject(_btFormat);
|
||||
_btFormat = null;
|
||||
}
|
||||
|
||||
if (_btApp != null)
|
||||
{
|
||||
_btApp.Quit(BtSaveOptions.btDoNotSaveChanges);
|
||||
System.Runtime.InteropServices.Marshal.ReleaseComObject(_btApp);
|
||||
_btApp = null;
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量打印多个List标签
|
||||
/// </summary>
|
||||
/// <param name="templatePath">标签模板路径</param>
|
||||
/// <param name="items">包含多个标签数据的列表</param>
|
||||
/// <param name="copiesPerItem">每个标签的打印份数</param>
|
||||
/// <param name="serializedLabels">序列化标签数量</param>
|
||||
/// <param name="getSubStringValues">从列表项获取标签变量的委托</param>
|
||||
/// <returns>是否全部打印成功</returns>
|
||||
public bool PrintLabels<T>(
|
||||
string templatePath,
|
||||
List<T> items,
|
||||
int copiesPerItem = 1,
|
||||
int serializedLabels = 1,
|
||||
Func<T, Dictionary<string, string>> getSubStringValues = null)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("BartenderPrintHelper", "对象已被释放,不能执行打印操作。");
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// 打开标签模板
|
||||
_btFormat = _btApp.Formats.Open(templatePath);
|
||||
|
||||
// 设置打印参数
|
||||
_btFormat.PrintSetup.IdenticalCopiesOfLabel = copiesPerItem;
|
||||
_btFormat.PrintSetup.NumberSerializedLabels = serializedLabels;
|
||||
|
||||
bool allSuccess = true;
|
||||
|
||||
// 遍历所有项目并打印
|
||||
foreach (var item in items)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取当前项的变量值
|
||||
var subStringValues = getSubStringValues?.Invoke(item);
|
||||
|
||||
// 设置标签变量值
|
||||
if (subStringValues != null)
|
||||
{
|
||||
foreach (var kvp in subStringValues)
|
||||
{
|
||||
_btFormat.SetNamedSubStringValue(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行打印
|
||||
_btFormat.PrintOut(false, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 记录错误但继续打印其他项
|
||||
allSuccess = false;
|
||||
// 可以在这里添加日志记录
|
||||
Console.WriteLine($"打印标签时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return allSuccess;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"批量打印标签时出错: {ex.Message}", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_btFormat != null)
|
||||
{
|
||||
_btFormat.Close(BtSaveOptions.btDoNotSaveChanges);
|
||||
System.Runtime.InteropServices.Marshal.ReleaseComObject(_btFormat);
|
||||
_btFormat = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 批量打印多个标签(新增方法)
|
||||
/// </summary>
|
||||
/// <param name="templatePath">标签模板路径</param>
|
||||
/// <param name="batchSubStringValues">多个标签的变量键值对列表</param>
|
||||
/// <param name="copiesPerLabel">每个标签的打印份数</param>
|
||||
/// <param name="serializedLabels">序列化标签数量</param>
|
||||
/// <returns>是否全部打印成功</returns>
|
||||
public bool PrintBatchLabels(
|
||||
string templatePath,
|
||||
List<Dictionary<string, string>> batchSubStringValues,
|
||||
int copiesPerLabel = 1,
|
||||
int serializedLabels = 1)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException(nameof(BartenderPrintHelper), "对象已被释放,不能执行打印操作。");
|
||||
|
||||
if (batchSubStringValues == null || batchSubStringValues.Count == 0)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// 打开标签模板(只打开一次,提升性能)
|
||||
_btFormat = _btApp.Formats.Open(templatePath);
|
||||
_btFormat.PrintSetup.IdenticalCopiesOfLabel = copiesPerLabel;
|
||||
_btFormat.PrintSetup.NumberSerializedLabels = serializedLabels;
|
||||
|
||||
bool allSuccess = true;
|
||||
|
||||
// 遍历所有标签数据并打印
|
||||
foreach (var subStringValues in batchSubStringValues)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 设置变量值
|
||||
foreach (var kvp in subStringValues)
|
||||
{
|
||||
_btFormat.SetNamedSubStringValue(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
// 执行打印(不关闭模板,继续复用)
|
||||
_btFormat.PrintOut(false, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
allSuccess = false;
|
||||
// 可记录日志或抛出特定异常
|
||||
Console.WriteLine($"打印标签时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return allSuccess;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"批量打印标签时出错: {ex.Message}", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保释放资源
|
||||
if (_btFormat != null)
|
||||
{
|
||||
_btFormat.Close(BtSaveOptions.btDoNotSaveChanges);
|
||||
System.Runtime.InteropServices.Marshal.ReleaseComObject(_btFormat);
|
||||
_btFormat = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~BartenderPrintHelper()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
172
linesider_screen_tool/Hepler/MQTTHepler.cs
Normal file
172
linesider_screen_tool/Hepler/MQTTHepler.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
|
||||
using MQTTnet;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace linesider_screen_tool
|
||||
{
|
||||
public class MQTTHepler
|
||||
{
|
||||
public IMqttClient _mqttClient;
|
||||
private MqttClientOptions _options;
|
||||
private readonly string _clientId;
|
||||
private readonly string _server;
|
||||
private readonly int _port;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly bool _cleanSession;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 MQTT 客户端
|
||||
/// </summary>
|
||||
public MQTTHepler(string server, int port = 1883, string clientId = null,
|
||||
string username = null, string password = null, bool cleanSession = true)
|
||||
{
|
||||
_server = server;
|
||||
_port = port;
|
||||
_clientId = clientId;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_cleanSession = cleanSession;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接到 MQTT 服务器
|
||||
/// </summary>
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
if (_mqttClient != null && _mqttClient.IsConnected)
|
||||
return;
|
||||
|
||||
var factory = new MqttFactory();
|
||||
_mqttClient = factory.CreateMqttClient();
|
||||
|
||||
// 先注册事件处理器
|
||||
//_mqttClient.ApplicationMessageReceivedAsync += HandleReceivedApplicationMessage;
|
||||
|
||||
var builder = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer(_server, _port)
|
||||
.WithClientId(_clientId) // 确保指定了 ClientId
|
||||
.WithCleanSession(_cleanSession);
|
||||
|
||||
if (!string.IsNullOrEmpty(_username))
|
||||
builder.WithCredentials(_username, _password);
|
||||
|
||||
_options = builder.Build();
|
||||
|
||||
_mqttClient.DisconnectedAsync += async e =>
|
||||
{
|
||||
Console.WriteLine($"MQTT 断开: {e.Reason}");
|
||||
await Task.Delay(5000);
|
||||
await ReconnectAsync();
|
||||
};
|
||||
|
||||
await _mqttClient.ConnectAsync(_options, CancellationToken.None);
|
||||
Console.WriteLine("MQTT 连接成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅主题
|
||||
/// </summary>
|
||||
public async Task SubscribeAsync(string topic, MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtLeastOnce)
|
||||
{
|
||||
if (_mqttClient == null || !_mqttClient.IsConnected)
|
||||
await ConnectAsync();
|
||||
|
||||
var topicFilter = new MqttTopicFilterBuilder()
|
||||
.WithTopic(topic)
|
||||
.WithQualityOfServiceLevel(qos)
|
||||
.Build();
|
||||
|
||||
var result = await _mqttClient.SubscribeAsync(topicFilter, CancellationToken.None);
|
||||
Console.WriteLine($"订阅结果: {result.Items.First().ResultCode}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布消息
|
||||
/// </summary>
|
||||
public async Task PublishAsync(string topic, string payload,MqttQualityOfServiceLevel qos = MqttQualityOfServiceLevel.AtLeastOnce,
|
||||
bool retain = false)
|
||||
{
|
||||
if (_mqttClient == null || !_mqttClient.IsConnected)
|
||||
await ConnectAsync();
|
||||
|
||||
var message = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic)
|
||||
.WithPayload(payload)
|
||||
.WithQualityOfServiceLevel(qos)
|
||||
.WithRetainFlag(retain)
|
||||
.Build();
|
||||
|
||||
try
|
||||
{
|
||||
await _mqttClient.PublishAsync(message, CancellationToken.None);
|
||||
Console.WriteLine($"已发布消息到主题 {topic}: {payload}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"发布消息失败: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消订阅主题
|
||||
/// </summary>
|
||||
public async Task UnsubscribeAsync(string topic)
|
||||
{
|
||||
if (_mqttClient == null || !_mqttClient.IsConnected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _mqttClient.UnsubscribeAsync(topic, CancellationToken.None);
|
||||
Console.WriteLine($"已取消订阅主题: {topic}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"取消订阅主题失败: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReconnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _mqttClient.ConnectAsync(_options, CancellationToken.None);
|
||||
Console.WriteLine("MQTT 重新连接成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"MQTT 重新连接失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DisconnectAsync()
|
||||
{
|
||||
if (_mqttClient == null || !_mqttClient.IsConnected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _mqttClient.DisconnectAsync();
|
||||
DisconnectAsync().Wait();
|
||||
_mqttClient?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
Console.WriteLine("MQTT 已断开连接");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"断开连接失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
87
linesider_screen_tool/Hepler/SerialPortHepler.cs
Normal file
87
linesider_screen_tool/Hepler/SerialPortHepler.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO.Ports;
|
||||
using System.Text.RegularExpressions;
|
||||
using MQTTnet;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace linesider_screen_tool
|
||||
{
|
||||
public class SerialPortHepler:IDisposable
|
||||
{
|
||||
private SerialPort _serialPort;
|
||||
// 内部缓冲区用于存储接收到的数据
|
||||
private StringBuilder receiveBuffer = new StringBuilder();
|
||||
public event Action<string> DataReceived;
|
||||
|
||||
public SerialPortHepler(string portName,int baudRaate,int parity,int dataBits,int stopBits)
|
||||
{
|
||||
_serialPort = new SerialPort(portName, baudRaate, (Parity)parity, dataBits, (StopBits)stopBits);
|
||||
}
|
||||
|
||||
public async void Open()
|
||||
{
|
||||
if (_serialPort != null && _serialPort.IsOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
_serialPort.Open();
|
||||
_serialPort.DataReceived += SerialPort_DataReceived;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
if (_serialPort == null || !_serialPort.IsOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
_serialPort.DataReceived -= SerialPort_DataReceived;
|
||||
_serialPort.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
string newData = _serialPort.ReadExisting();
|
||||
receiveBuffer.Append(newData);
|
||||
|
||||
// 处理缓冲区中的数据
|
||||
string bufferContent = receiveBuffer.ToString();
|
||||
string[] lines = Regex.Split(bufferContent, @"\r\n|\n|\r", RegexOptions.None);
|
||||
|
||||
for (int i = 0; i < lines.Length - 1; i++)
|
||||
{
|
||||
string line = lines[i].Trim();
|
||||
if (!string.IsNullOrEmpty(line))
|
||||
DataReceived.Invoke(line); ;
|
||||
}
|
||||
// 将最后一行保留到缓冲区中
|
||||
receiveBuffer.Clear();
|
||||
if (lines.Length > 0)
|
||||
{
|
||||
receiveBuffer.Append(lines[lines.Length - 1]);
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
_serialPort?.Dispose();
|
||||
_serialPort = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user