add-添加ZPL指令打印机服务(原材料、成品条码、配对码)

dev
liuwf 1 month ago
parent 8f27f95f2b
commit fd63392361

@ -0,0 +1,134 @@
using PrintBarCode.Helper;
using PrintBarCode.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrintBarCode.Business
{
public class PrintBusiness
{
private DebugConfig debugConfig = DebugConfig.Instance;
private static string basePath = AppDomain.CurrentDomain.BaseDirectory;
PrintHelper PrintH = new PrintHelper();
private RawPrinterHelper zplp = new RawPrinterHelper();
public PrintBusiness()
{
}
/// <summary>
/// 打印原材料条码方法
/// </summary>
public void PrintRawBarCodeInfo(RawBarCodeInfo rawBarCodeInfo)
{
// 拼接成目标文件的完整路径
string path = Path.Combine(basePath, "templates", "rawTemplate.prn");
//
string[] args = new string[]
{
rawBarCodeInfo.MaterialName,
rawBarCodeInfo.MaterialCode,
rawBarCodeInfo.MaterialSpec,
rawBarCodeInfo.BatchCode,
rawBarCodeInfo.PoNo,
rawBarCodeInfo.SaleOrderCode,
rawBarCodeInfo.Barcode,
rawBarCodeInfo.QrCode,
};
// 将属性值用 "~" 连接起来,不带前缀
string TempStr = $"{rawBarCodeInfo.MaterialName}~{rawBarCodeInfo.MaterialCode}~{rawBarCodeInfo.MaterialSpec}~{rawBarCodeInfo.BatchCode}~{rawBarCodeInfo.PoNo}~{rawBarCodeInfo.SaleOrderCode}~{rawBarCodeInfo.Barcode}~{rawBarCodeInfo.QrCode}";
string ZplStr = PrintH.GetPrintString(path, TempStr);//替换后字符串
bool pringFlag = zplp.SendStringToPrinter(debugConfig.PrintName, ZplStr);
if (pringFlag == false)
{
Console.WriteLine("打印错误,检查后请重新操作!");
}
}
/// <summary>
/// 打印成品条码方法
/// </summary>
public void PrintProductBarCodeInfo(ProductBarCodeInfo productBarCodeInfo)
{
// 拼接成目标文件的完整路径
string path = Path.Combine(basePath, "templates", "productTemplate.prn");
//
string[] args = new string[]
{
productBarCodeInfo.MaterialName,
productBarCodeInfo.MaterialCode,
productBarCodeInfo.MaterialSpec,
productBarCodeInfo.ProductPlanCode,
productBarCodeInfo.SaleOrderCode,
productBarCodeInfo.BarCode,
productBarCodeInfo.Qty,
productBarCodeInfo.QrCode,
};
string TempStr = $"{productBarCodeInfo.MaterialName}~{productBarCodeInfo.MaterialCode}~{productBarCodeInfo.MaterialSpec}~{productBarCodeInfo.ProductPlanCode}~{productBarCodeInfo.SaleOrderCode}~{productBarCodeInfo.BarCode}~{productBarCodeInfo.Qty}~{productBarCodeInfo.QrCode}";
string ZplStr = PrintH.GetPrintString(path, TempStr);//替换后字符串
bool pringFlag = zplp.SendStringToPrinter(debugConfig.PrintName, ZplStr);
if (pringFlag == false)
{
Console.WriteLine("打印错误,检查后请重新操作!");
}
}
/// <summary>
/// 打印配对码方法
/// </summary>
public void PrintBindBarCodeInfo(BindBarCodeInfo bindBarCodeInfo)
{
// 拼接成目标文件的完整路径
string path = Path.Combine(basePath, "templates", "bindTemplate.prn");
//
string[] args = new string[]
{
bindBarCodeInfo.MaterialName,
bindBarCodeInfo.MaterialCode,
bindBarCodeInfo.MaterialSpec,
bindBarCodeInfo.BatchCode,
bindBarCodeInfo.PoNo,
bindBarCodeInfo.SaleOrderCode,
bindBarCodeInfo.Barcode,
bindBarCodeInfo.QrCode,
};
// 将属性值用 "~" 连接起来,不带前缀
string TempStr = $"{bindBarCodeInfo.MaterialName}~{bindBarCodeInfo.MaterialCode}~{bindBarCodeInfo.MaterialSpec}~{bindBarCodeInfo.BatchCode}~{bindBarCodeInfo.PoNo}~{bindBarCodeInfo.SaleOrderCode}~{bindBarCodeInfo.Barcode}~{bindBarCodeInfo.QrCode}";
string ZplStr = PrintH.GetPrintString(path, TempStr);//替换后字符串
bool pringFlag = zplp.SendStringToPrinter(debugConfig.PrintName, ZplStr);
if (pringFlag == false)
{
Console.WriteLine("打印错误,检查后请重新操作!");
}
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace PrintBarCode.DTO
{
public class Output
{
[JsonPropertyName("template")]
public string Template { get; set; }
[JsonPropertyName("printContent")]
public string PrintContent { get; set; }
}
}

@ -0,0 +1,53 @@

using System;
using System.Collections.Generic;
namespace PrintBarCode.Helper
{
/// <summary>
/// 系统配置
/// </summary>
public sealed class DebugConfig
{
private static IniHelper iniHelper = new IniHelper(System.Environment.CurrentDirectory + "/config/App.InI");
private static readonly Lazy<DebugConfig> lazy = new Lazy<DebugConfig>(() => new DebugConfig());
public static DebugConfig Instance
{
get
{
return lazy.Value;
}
}
public DebugConfig()
{
}
/// <summary>
//打印机名称
/// </summary>
public string PrintName
{
get { return iniHelper.IniReadValue("system", "PrintName"); }
set { iniHelper.IniWriteValue("system", "PrintName", value); }
}
/// <summary>
//所在电脑IP
/// </summary>
public string IP
{
get { return iniHelper.IniReadValue("system", "IP"); }
set { iniHelper.IniWriteValue("system", "IP", value); }
}
}
}

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PrintBarCode.Helper
{
public class IniHelper
{
public string path;
public IniHelper(string INIPath)
{
path = INIPath;
}
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
[DllImport("kernel32", EntryPoint = "GetPrivateProfileString")]
private static extern uint GetPrivateProfileStringA(string section, string key, string def, Byte[] retVal, int size, string filePath);
/// <summary>
/// 写INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.path);
}
/// <summary>
/// 读取INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <returns></returns>
public string IniReadValue(string Section, string Key)
{
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
//return temp.ToString();
string str = temp.ToString();
return str;
}
public byte[] IniReadValues(string section, string key)
{
byte[] temp = new byte[255];
int i = GetPrivateProfileString(section, key, "", temp, 255, this.path);
return temp;
}
/// <summary>
/// 删除ini文件下所有段落
/// </summary>
public void ClearAllSection()
{
IniWriteValue(null, null, null);
}
/// <summary>
/// 删除ini文件下personal段落下的所有键
/// </summary>
/// <param name="Section"></param>
public void ClearSection(string Section)
{
IniWriteValue(Section, null, null);
}
public List<string> ReadKeys(String SectionName)
{
return ReadKeys(SectionName, this.path);
}
public List<string> ReadKeys(string SectionName, string iniFilename)
{
List<string> result = new List<string>();
Byte[] buf = new Byte[65536];
uint len = GetPrivateProfileStringA(SectionName, null, null, buf, buf.Length, iniFilename);
int j = 0;
for (int i = 0; i < len; i++)
if (buf[i] == 0)
{
result.Add(Encoding.Default.GetString(buf, j, i - j));
j = i + 1;
}
return result;
}
}
}

@ -0,0 +1,51 @@
using PrintBarCode.DTO;
using PrintBarCode.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace PrintBarCode.Helper
{
public class JsonParser
{
public static List<object> ParseJson(string jsonString)
{
try
{
// 解析外层的 JSON 字符串
var output = JsonSerializer.Deserialize<Output>(jsonString);
// 根据 template 字段选择不同的解析方式
if (output.Template == "raw")
{
var rawBarCodeInfoList = JsonSerializer.Deserialize<List<RawBarCodeInfo>>(output.PrintContent);
return rawBarCodeInfoList.Cast<object>().ToList();
}
else if (output.Template == "product")
{
var productBarCodeInfoList = JsonSerializer.Deserialize<List<ProductBarCodeInfo>>(output.PrintContent);
return productBarCodeInfoList.Cast<object>().ToList();
}
else if(output.Template == "bind")
{
var bindBarCodeInfoList = JsonSerializer.Deserialize<List<BindBarCodeInfo>>(output.PrintContent);
return bindBarCodeInfoList.Cast<object>().ToList();
}
else
{
return null;
}
}
catch (JsonException ex)
{
Console.WriteLine($"Failed to parse JSON: {ex.Message}");
return null;
}
}
}
}

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace PrintBarCode.Helper
{
public class NetworkHelper
{
/// <summary>
/// 获取本地计算机的所有 IPv4 地址。
/// </summary>
/// <returns>IPv4 地址列表。如果没有找到,则返回一个空列表。</returns>
public static List<string> GetLocalIPv4Addresses()
{
List<string> ipAddresses = new List<string>();
try
{
// 获取所有网络接口
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var networkInterface in networkInterfaces)
{
// 检查网络接口是否处于正常状态且不是回环接口
if (networkInterface.OperationalStatus == OperationalStatus.Up &&
networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback)
{
// 获取该接口的IP属性
var ipProperties = networkInterface.GetIPProperties();
// 获取单播地址集合
var unicastAddresses = ipProperties.UnicastAddresses;
foreach (var address in unicastAddresses)
{
// 检查是否是 IPv4 地址
if (address.Address.AddressFamily == AddressFamily.InterNetwork)
{
// 获取 IPv4 地址并添加到列表
var ipAddress = address.Address.ToString();
if (!string.IsNullOrEmpty(ipAddress) && !ipAddress.StartsWith("169.254")) // 排除自动私有地址
{
ipAddresses.Add(ipAddress);
}
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("获取IP地址时发生错误: " + ex.Message);
}
return ipAddresses;
}
/// <summary>
/// 获取本地计算机的第一个有效的 IPv4 地址。
/// </summary>
/// <returns>第一个有效的 IPv4 地址,如果没有找到则返回 null。</returns>
public static string GetFirstLocalIPv4Address()
{
var ipAddresses = GetLocalIPv4Addresses();
return ipAddresses.Count > 0 ? ipAddresses[0] : null;
}
}
}

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Metrics;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace PrintBarCode.Helper
{
public class PrintHelper
{
private DataTable dt = new DataTable();
public PrintHelper()
{
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Value", typeof(string));
dt.Columns.Add("Size", typeof(string));
}
public string GetPrintString(string path, string PrintStr)
{
string[] array = File.ReadAllLines(path, Encoding.Default);
int count2 = 0;
for (int num = array.Length - 1; num >= 0; num--)
{
if (array[num].IndexOf("%%") > -1)
{
count2++; // 每找到一个包含“%%”的行计数器加1
}
}
for (int num = array.Length - 1; num >= 0; num--)
{
if (array[num].IndexOf("%%") > -1)
{
string sourse = array[num];
string text = MidStrEx_New(sourse, "A0N,", "FH");
int fontSize = GetFontSize(text);
string text2 = MidStrEx_New(sourse, "FD%%", "FS");
string value = "%%" + text2.Split('^')[0];
DataRow dataRow = dt.NewRow();
dataRow[0] = value;
dataRow[1] = text;
dataRow[2] = fontSize.ToString();
dt.Rows.Add(dataRow);
}
else if (array[num].IndexOf("^LL") > -1)
{
break;
}
}
string boxFlie = getBoxFlie(path);
return replaceGXStr(PrintStr, boxFlie);
}
private string MidStrEx_New(string sourse, string startstr, string endstr)
{
Regex regex = new Regex("(?<=(" + startstr + "))[.\\s\\S]*?(?=(" + endstr + "))", RegexOptions.Multiline | RegexOptions.Singleline);
return regex.Match(sourse).Value;
}
private int GetFontSize(string hw)
{
int result = 9;
string[] array = hw.Split(',');
try
{
result = (int)(Convert.ToDouble(array[0]) / 2.8 + 0.4);
}
catch
{
}
return result;
}
private string ConvertImageToCode(Bitmap img)
{
StringBuilder stringBuilder = new StringBuilder();
long num = 0L;
long num2 = 0L;
int num3 = 0;
for (int i = 0; i < img.Size.Height; i++)
{
for (int j = 0; j < img.Size.Width; j++)
{
num3 *= 2;
string text = ((long)img.GetPixel(j, i).ToArgb()).ToString("X");
if (text.Substring(text.Length - 6, 6).CompareTo("BBBBBB") < 0)
{
num3++;
}
num2++;
if (j == img.Size.Width - 1 && num2 < 8)
{
stringBuilder.Append((num3 * (2 ^ (8 - (int)num2))).ToString("X").PadLeft(2, '0'));
num3 = 0;
num2 = 0L;
}
if (num2 >= 8)
{
stringBuilder.Append(num3.ToString("X").PadLeft(2, '0'));
num3 = 0;
num2 = 0L;
}
}
stringBuilder.Append(Environment.NewLine);
}
return stringBuilder.ToString();
}
private Bitmap CreateImage(string data, Font f)
{
if (string.IsNullOrEmpty(data))
{
return null;
}
TextBox textBox = new TextBox();
textBox.Text = data;
textBox.Font = f;
Bitmap bitmap = new Bitmap(textBox.PreferredSize.Width, (textBox.PreferredSize.Height - 5) * textBox.Lines.Length + 5);
Graphics graphics = Graphics.FromImage(bitmap);
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, bitmap.Width, bitmap.Height), Color.Black, Color.Black, 1.2f, isAngleScaleable: true);
graphics.Clear(Color.White);
graphics.DrawString(data, f, brush, 1f, 1f);
return bitmap;
}
private string ZPLStr(string data, string name, float Size = 9f)
{
Bitmap bitmap = CreateImage(data, new Font("黑体", Size, FontStyle.Bold));
string text = ((bitmap.Size.Width / 8 + ((bitmap.Size.Width % 8 != 0) ? 1 : 0)) * bitmap.Size.Height).ToString();
string text2 = (bitmap.Size.Width / 8 + ((bitmap.Size.Width % 8 != 0) ? 1 : 0)).ToString();
string text3 = ConvertImageToCode(bitmap);
return $"~DGR:{name}.GRF,{text},{text2},{text3}";
}
private bool HasChinese(string str)
{
return Regex.IsMatch(str, "[\\u4e00-\\u9fa5]");
}
private string replaceGXStr(string list, string boxStr)
{
string text = boxStr;
string[] array = list.Split('~');
if (!HasChinese(list))
{
for (int num = array.Length; num >= 1; num--)
{
text = text.Replace("%%" + num, array[num - 1]);
}
}
else
{
for (int num2 = array.Length; num2 >= 1; num2--)
{
string text2 = array[num2 - 1];
if (HasChinese(text2))
{
float size = Convert.ToInt16(dt.Select("Name = '%%" + num2 + "'")[0]["Size"].ToString());
string text3 = ZPLStr(text2, num2.ToString(), size);
text = text.Replace("^LS0", "^LS0\r\n" + text3);
text = text.Replace("FD%%" + num2, "XGR:" + num2 + ".GRF");
text = text.Replace("FD##" + num2, "XGR:" + num2 + ".GRF");
text = text + "\r\n^XA^ID" + num2 + ".GRF^FS^XZ";
}
else
{
text = text.Replace("%%" + num2, array[num2 - 1]);
}
}
}
return text;
}
private string getBoxFlie(string _path)
{
FileStream fileStream = new FileStream(_path, FileMode.Open);
fileStream.Seek(0L, SeekOrigin.Begin);
BinaryReader binaryReader = new BinaryReader(fileStream, Encoding.Default);
byte[] array = new byte[fileStream.Length];
ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
string text = "";
array = binaryReader.ReadBytes(array.Length);
text = Encoding.Default.GetString(array);
fileStream.Close();
binaryReader.Close();
return text;
}
}
}

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PrintBarCode.Helper
{
class RawPrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
// SendBytesToPrinter()
// When the function is given a printer name and an unmanaged array
// of bytes, the function sends those bytes to the print queue.
// Returns true on success, false on failure.
public bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
di.pDocName = "My C#.NET RAW Document";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// Start a document.
if (StartDocPrinter(hPrinter, 1, di))
{
// Start a page.
if (StartPagePrinter(hPrinter))
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
}
return bSuccess;
}
public bool SendFileToPrinter(string szPrinterName, string szFileName)
{
// Open the file.
FileStream fs = new FileStream(szFileName, FileMode.Open);
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte[] bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
int nLength;
nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes(nLength);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
}
public bool SendStringToPrinter(string szPrinterName, string szString)
{
IntPtr pBytes;
Int32 dwCount;
// How many characters are in the string?
dwCount = szString.Length;
// Assume that the printer is expecting ANSI text, and then convert
// the string to ANSI text.
pBytes = Marshal.StringToCoTaskMemAnsi(szString);
// Send the converted ANSI string to the printer.
SendBytesToPrinter(szPrinterName, pBytes, dwCount);
Marshal.FreeCoTaskMem(pBytes);
return true;
}
}
}

@ -0,0 +1,61 @@
namespace PrintBarCode
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
label1 = new Label();
SuspendLayout();
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Microsoft YaHei UI", 21.75F, FontStyle.Bold, GraphicsUnit.Point);
label1.Location = new Point(76, 115);
label1.Name = "label1";
label1.Size = new Size(307, 39);
label1.TabIndex = 0;
label1.Text = "打印条码服务启动成功";
//
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(451, 262);
Controls.Add(label1);
Name = "MainForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "打印条码服务";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label label1;
}
}

@ -0,0 +1,20 @@
using PrintBarCode.Business;
using PrintBarCode.Helper;
using PrintBarCode.Model;
using SlnMesnac.Redis;
namespace PrintBarCode
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
}
}

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing"">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

@ -0,0 +1,117 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PrintBarCode.Business;
using PrintBarCode.Helper;
using PrintBarCode.Model;
using ServiceStack.Messaging;
using SlnMesnac.Common;
using SlnMesnac.Model.domain;
using SlnMesnac.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrintBarCode
{
public class MessageClient
{
private readonly RedisHandler _redisHandler;
private PrintBusiness printBusiness = new PrintBusiness();
private readonly DebugConfig debugConfig = DebugConfig.Instance;
public MessageClient(RedisHandler redisHandler)
{
_redisHandler = redisHandler;
string ip = NetworkHelper.GetFirstLocalIPv4Address();
debugConfig.IP = ip;
}
public void StartListening()
{
Console.WriteLine($"启动打印监听服务~~~");
Listening();
// 订阅当前工位的频道
_redisHandler.SubscribeToChannel($"print_{debugConfig.IP}", OnMessageReceivedByWorkId);
Console.WriteLine($"订阅工位 ===》print_{debugConfig.IP} 成功");
// 订阅当前工位的频道
// 开始处理队列中的未消费消息
// ProcessMessageQueue();
// _redisHandler.SubscribeToChannel("read_messages", OnMessageReceived);
}
private async void OnMessageReceivedByWorkId(string channelWork, string messageId)
{
try
{
var message = _redisHandler.ConsumeMessageFromWorker(debugConfig.IP);
if (!string.IsNullOrEmpty(message))
{
Console.WriteLine($"消息: {message}");
}
}
catch (Exception ex)
{
Console.WriteLine("处理消息时发生错误");
}
}
private void Listening()
{
Task.Run(() =>
{
Thread.Sleep(1000 * 2);
while (true)
{
try
{
string channelWork = $"print_{debugConfig.IP}";
string jsonString = _redisHandler.ConsumeMessageFromWorker(channelWork);
// string jsonString = "{\"template\":\"product\",\"printContent\":\"[{\\\"saleOrderCode\\\":\\\"\\\",\\\"materialName\\\":\\\"多功能自动剥线钳\\\",\\\"qrcode\\\":\\\"20241019112921CP001\\\",\\\"materialSpec\\\":\\\"\\\",\\\"qty\\\":\\\"1\\\",\\\"materialCode\\\":\\\"MES.MC.A00861\\\",\\\"barcode\\\":\\\"20241019112921CP001\\\",\\\"productPlanCode\\\":\\\"20241019111402JL012\\\"}]\"}";
if (!string.IsNullOrEmpty(jsonString))
{
var result = JsonParser.ParseJson(jsonString);
if (result != null)
{
foreach (var item in result)
{
if (item is RawBarCodeInfo rawBarCodeInfo)
{
printBusiness.PrintRawBarCodeInfo(rawBarCodeInfo);
Console.WriteLine($"SaleOrderCode: {rawBarCodeInfo.SaleOrderCode}, MaterialName: {rawBarCodeInfo.MaterialName}, PoNo: {rawBarCodeInfo.PoNo}, QrCode: {rawBarCodeInfo.QrCode}, BatchCode: {rawBarCodeInfo.BatchCode}, MaterialSpec: {rawBarCodeInfo.MaterialSpec}, MaterialCode: {rawBarCodeInfo.MaterialCode}, Barcode: {rawBarCodeInfo.Barcode}");
}
else if (item is ProductBarCodeInfo productBarCodeInfo)
{
printBusiness.PrintProductBarCodeInfo(productBarCodeInfo);
}else if (item is BindBarCodeInfo bindBarCodeInfo)
{
printBusiness.PrintBindBarCodeInfo(bindBarCodeInfo);
}
Thread.Sleep(1000);
}
}
}
Thread.Sleep(1000 * 1);
}
catch (Exception ex)
{
Console.WriteLine("处理消息时发生错误");
}
}
});
}
}
}

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace PrintBarCode.Model
{
public class BindBarCodeInfo
{
[JsonPropertyName("saleOrderCode")]
public string SaleOrderCode { get; set; }
[JsonPropertyName("materialName")]
public string MaterialName { get; set; }
[JsonPropertyName("poNo")]
public string PoNo { get; set; }
[JsonPropertyName("qrcode")]
public string QrCode { get; set; }
[JsonPropertyName("batchCode")]
public string BatchCode { get; set; }
[JsonPropertyName("materialSpec")]
public string MaterialSpec { get; set; }
[JsonPropertyName("materialCode")]
public string MaterialCode { get; set; }
[JsonPropertyName("barcode")]
public string Barcode { get; set; }
}
}

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace PrintBarCode.Model
{
public class ProductBarCodeInfo
{
[JsonPropertyName("materialName")]
public string MaterialName { get; set; }
[JsonPropertyName("qrcode")]
public string QrCode { get; set; }
[JsonPropertyName("materialSpec")]
public string MaterialSpec { get; set; }
[JsonPropertyName("qty")]
public string Qty { get; set; }
[JsonPropertyName("materialCode")]
public string MaterialCode { get; set; }
[JsonPropertyName("barcode")]
public string BarCode { get; set; }
[JsonPropertyName("productPlanCode")]
public string ProductPlanCode { get; set; }
[JsonPropertyName("saleOrderCode")]
public string SaleOrderCode { get; set; }
}
}

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace PrintBarCode.Model
{
public class RawBarCodeInfo
{
[JsonPropertyName("saleOrderCode")]
public string SaleOrderCode { get; set; }
[JsonPropertyName("materialName")]
public string MaterialName { get; set; }
[JsonPropertyName("poNo")]
public string PoNo { get; set; }
[JsonPropertyName("qrcode")]
public string QrCode { get; set; }
[JsonPropertyName("batchCode")]
public string BatchCode { get; set; }
[JsonPropertyName("materialSpec")]
public string MaterialSpec { get; set; }
[JsonPropertyName("materialCode")]
public string MaterialCode { get; set; }
[JsonPropertyName("barcode")]
public string Barcode { get; set; }
}
}

@ -0,0 +1,66 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<None Remove="appsettings.json" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SlnMesnac.Business\SlnMesnac.Business.csproj" />
<ProjectReference Include="..\SlnMesnac.Common\SlnMesnac.Common.csproj" />
<ProjectReference Include="..\SlnMesnac.Config\SlnMesnac.Config.csproj" />
<ProjectReference Include="..\SlnMesnac.Extensions\SlnMesnac.Extensions.csproj" />
<ProjectReference Include="..\SlnMesnac.Generate\SlnMesnac.Generate.csproj" />
<ProjectReference Include="..\SlnMesnac.Ioc\SlnMesnac.Ioc.csproj" />
<ProjectReference Include="..\SlnMesnac.Model\SlnMesnac.Model.csproj" />
<ProjectReference Include="..\SlnMesnac.Redis\SlnMesnac.Redis.csproj" />
<ProjectReference Include="..\SlnMesnac.Repository\SlnMesnac.Repository.csproj" />
<ProjectReference Include="..\SlnMesnac.Serilog\SlnMesnac.Serilog.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="BarcodeStandard">
<HintPath>DLL\BarcodeStandard.dll</HintPath>
</Reference>
<Reference Include="BinaryKits.Zpl.Label">
<HintPath>DLL\BinaryKits.Zpl.Label.dll</HintPath>
</Reference>
<Reference Include="BinaryKits.Zpl.Viewer">
<HintPath>DLL\BinaryKits.Zpl.Viewer.dll</HintPath>
</Reference>
<Reference Include="Neodynamic.SDK.ZPLPrinter">
<HintPath>DLL\Neodynamic.SDK.ZPLPrinter.dll</HintPath>
</Reference>
<Reference Include="QRCoder">
<HintPath>DLL\QRCoder.dll</HintPath>
</Reference>
<Reference Include="SixLabors.ImageSharp">
<HintPath>DLL\SixLabors.ImageSharp.dll</HintPath>
</Reference>
<Reference Include="SkiaSharp">
<HintPath>DLL\SkiaSharp.dll</HintPath>
</Reference>
<Reference Include="ZPLPrintDLL">
<HintPath>DLL\ZPLPrintDLL.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -0,0 +1,39 @@
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
namespace PrintBarCode
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
host.RunAsync();
ApplicationConfiguration.Initialize();
Application.Run(new MainForm());
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureServices((hostContext, services) =>
{
//services.AddHostedService<ReadBusiness>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<PrintBarCode.Startup>();
});
}
}

@ -0,0 +1,112 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SlnMesnac.Config;
using SlnMesnac.Serilog;
using System;
using Autofac;
using Microsoft.Extensions.Configuration;
using SlnMesnac.Ioc;
using SlnMesnac.Extensions;
using SlnMesnac.Generate;
using SlnMesnac.TouchSocket;
using SlnMesnac.Redis;
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2024 WenJY
* CLR4.0.30319.42000
* LAPTOP-E0N2L34V
* ConsoleApp
* 04133b44-1390-4f6a-aaef-88f4127d88f0
*
* WenJY
* wenjy@mesnac.com
* 2024-04-23 18:06:27
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace PrintBarCode
{
/// <summary>
///
/// </summary>
public class Startup
{
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
/// <summary>
///
/// </summary>
public IConfiguration Configuration { get; }
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
[Obsolete]
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<RedisHandler>();
services.AddSingleton<PrintBarCode.MessageClient>();
//注册AppConfig
services.AddSingleton<AppConfig>(provider =>
{
var configuration = provider.GetService<IConfiguration>();
return configuration.GetSection("AppConfig").Get<AppConfig>();
});
//注册ORM
services.AddSqlSugarSetup();
//// 注册 ElectricBusiness
//services.AddScoped<ElectricBusiness>();
}
/// <summary>
/// AutoFac自动注入
/// </summary>
/// <param name="builder"></param>
public void ConfigureContainer(ContainerBuilder builder)
{
DependencyConfigurator.Configure(builder);
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, PrintBarCode.MessageClient messageClient)
{
messageClient.StartListening();
//启用Serilog中间件
app.UseSerilogExtensions();
}
}
}

@ -0,0 +1,78 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"AppConfig": {
"logPath": "E:\\c#\\京源环保\\程序设计\\生产控制\\SlnMesnac\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows",
"stationId": 11,
"SqlConfig": [
{
"configId": "mes",
"dbType": 0,
// "connStr": "Data Source=175.27.215.92;Port=3306;Initial Catalog=hwjy-cloud;uid=root;pwd=haiwei@123;Charset=utf8mb4;SslMode=none"
"connStr": "Data Source=172.16.12.100;Port=3306;Initial Catalog=hwjy-cloud;uid=root;pwd=JyhbRk@123456;Charset=utf8mb4;SslMode=none"
},
{
"configId": "local",
"dbType": 2,
"connStr": "DataSource=E:\\c#\\京源环保\\程序设计\\生产控制\\SlnMesnac\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows\\data\\data.db"
}
//{
// "configId": "mesTD",
// "dbType": 17,
// "connStr": "Host=175.27.215.92;Port=6030;Username=root;Password=taosdata;Database=db_hwmes"
//},
//{
// "configId": "scada",
// "dbType": 0,
// "connStr": "Data Source=175.27.215.92;Port=3306;Initial Catalog=jy-scada;uid=root;pwd=haiwei@123;Charset=utf8mb4;SslMode=none"
//}
],
"PlcConfig": [
{
"configId": 1,
"plcType": "SiemensPlc",
"plcIp": "192.168.2.220",
// "plcIp": "127.0.0.1",
"plcPort": 102,
"plcKey": "plc",
"isFlage": true
},
{
"configId": 2, //MES
"plcType": "SiemensPlc",
"plcIp": "127.0.0.1",
"plcPort": 103,
"plcKey": "mesSingal",
"isFlage": false
}
],
"RfidConfig": [
{
// RFID
"configId": 1,
"equipIp": "192.168.2.27",
"equipPort": 20108,
"equipKey": "secondFloorPallet",
"isFlage": true
},
{
// RFID
"configId": 2,
"equipIp": "192.168.2.28",
"equipPort": 20108,
"equipKey": "secondFloorOut",
"isFlage": true
}
],
"redisConfig": "172.16.12.100:6379,password=JyhbRk@2024"
// "redisConfig": "175.27.215.92:6379,password=redis@2023"
}
}

@ -1,6 +1,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ServiceStack.Messaging;
using SlnMesnac.Common;
using SlnMesnac.Config;
using SlnMesnac.Model.domain;
@ -28,15 +29,47 @@ namespace ReadService
public void StartListening()
{
Console.WriteLine("启动监听朗读声音服务~~~");
_redisHandler.SubscribeToChannel("read_messages", OnMessageReceived);
Console.WriteLine($"启动监听朗读声音服务~~~");
// 订阅当前工位的频道
//_redisHandler.SubscribeToChannel($"channel_worker_{_appConfig.stationId}", OnMessageReceivedByWorkId);
//Console.WriteLine($"订阅工位 ===》channel_worker_{_appConfig.stationId} 成功");
// 订阅当前工位的频道
_redisHandler.SubscribeToChannel($"read_messages_public", OnMessageReceived);
Console.WriteLine($"订阅公共频道==>read_messages_public 成功");
// 开始处理队列中的未消费消息
// ProcessMessageQueue();
// _redisHandler.SubscribeToChannel("read_messages", OnMessageReceived);
}
//private async void OnMessageReceivedByWorkId(string channelWork, string messageId)
//{
// try
// {
// var message = _redisHandler.ConsumeMessageFromWorker(_appConfig.stationId);
// if (!string.IsNullOrEmpty(message))
// {
// await SpeechStr.Instance.SpeakAsync(message);
// Console.WriteLine($"客户端专属频道朗读消息: {message}");
// }
// }
// catch (Exception ex)
// {
// _logger.LogError(ex, "处理消息时发生错误");
// }
//}
/// <summary>
/// 公共频道
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
private async void OnMessageReceived(string channel, string message)
{
await SpeechStr.Instance.SpeakAsync(message);
Console.WriteLine($"客户端朗读消息{message}");
await SpeechStr.Instance.SpeakAsync(message);
Console.WriteLine($"客户端公共频道朗读消息{message}");
}
}
}

@ -9,7 +9,7 @@
"AllowedHosts": "*",
"AppConfig": {
"logPath": "E:\\c#\\京源环保\\程序设计\\生产控制\\SlnMesnac\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows",
"stationId": 11,
"stationId": 231,
"SqlConfig": [
{
"configId": "mes",
@ -72,5 +72,6 @@
}
],
"redisConfig": "172.16.12.100:6379,password=JyhbRk@2024"
}
}

@ -46,7 +46,7 @@ namespace SlnMesnac.Business
{
Log.Information($"总次数:{mesProductReadInfo.ReadTotal} 朗读第次数{mesProductReadInfo.ReadCount} 开始朗读:====>{mesProductReadInfo.ReadInfo}");
// SpeechStr.Instance.Speak(mesProductReadInfo.ReadInfo);
_redisHandler.PublishMessage("read_messages", mesProductReadInfo.ReadInfo);
_redisHandler.PublishMessage("read_messages_public", mesProductReadInfo.ReadInfo);
mesProductReadInfo.ReadCount++;
mesProductReadInfo.ReadStatus = 1;
mesProductReadInfo.UpdateTime = DateTime.Now;

@ -45,7 +45,6 @@ namespace SlnMesnac.Common
{
try
{
//端口名 注:因为使用的是USB转RS232 所以去设备管理器中查看一下虚拟com口的名字
serialPort.PortName = "COM1";// portName;
//波特率 霍尼威尔扫码枪115200,普通9600

@ -62,6 +62,8 @@ namespace SlnMesnac.Config
/// </summary>
public string redisConfig { get; set; }
public AppConfig Value => this;
}
}

@ -42,7 +42,7 @@ namespace SlnMesnac.Redis
private readonly ISubscriber _subscriber;
private readonly ConnectionMultiplexer redis;
public readonly ConnectionMultiplexer redis;
public RedisHandler(AppConfig appConfig, ILogger<RedisHandler> logger)
{
@ -62,11 +62,76 @@ namespace SlnMesnac.Redis
/// <param name="message"></param>
public void PublishMessage(string channel, string message)
{
long res = _subscriber.Publish(channel, message);
// 生成唯一的消息ID
// var messageId = $"{DateTime.UtcNow.Ticks}_{Guid.NewGuid().ToString("N")}";
// 存储消息内容
// var redisDb = redis.GetDatabase();
// redisDb.StringSet(messageId, message, TimeSpan.FromMinutes(10)); // 设置消息的有效期
// 发布消息ID
long res = _subscriber.Publish(channel, message);
_logger.LogInformation($"向主题:{channel};推送消息:{message};结果:{res}");
}
/// <summary>
/// 推送消息到指定工位的队列
/// </summary>
/// <param name="workerId">工位ID</param>
/// <param name="message">消息内容</param>
public void PublishMessageToWorker(int workerId, string message)
{
var channel = $"channel_worker_{workerId}";
// 生成唯一的消息ID
var messageId = $"{DateTime.UtcNow.Ticks}_{Guid.NewGuid().ToString("N")}";
// 存储消息内容,使用列表结构
var redisDb = redis.GetDatabase();
redisDb.ListRightPush(channel, message); // 将消息推入对应工位的队列
_logger.LogInformation($"向工位:{workerId} 的队列推送消息ID:{messageId},消息内容:{message}");
}
/// <summary>
/// 指定工位,从队列中获取一条消息(客户端消费时使用)
/// </summary>
/// <param name="workerId">工位ID</param>
/// <returns>消息内容如果没有消息则返回null</returns>
public string ConsumeMessageFromWorker(string workId,int dataBaseId = 0)
{
var channel = workId;
var redisDb = redis.GetDatabase(dataBaseId);
// 从队列左侧弹出消息
var message = redisDb.ListLeftPop(channel);
if (message.IsNull)
{
return null;
}
return (string)message;
}
/// <summary>
/// 确认消息
/// </summary>
/// <param name="messageId"></param>
public void AcknowledgeMessage(string messageId)
{
var redisDb = redis.GetDatabase();
redisDb.KeyDelete(messageId); // 删除确认的消息
_logger.LogInformation($"消息ID:{messageId} 已被确认处理");
}
/// <summary>
/// 订阅消息
/// </summary>
@ -81,17 +146,5 @@ namespace SlnMesnac.Redis
});
}
public void CleanExpiredMessages(string channel)
{
var redis = _subscriber.Multiplexer.GetDatabase();
redis.KeyDelete(channel);
}
public void SetValue(string key,string message)
{
IDatabase db = redis.GetDatabase(0);
TimeSpan expiry = TimeSpan.FromSeconds(10);
db.StringSet(key, message, expiry);
}
}
}

@ -39,7 +39,7 @@
"configId": 1,
"plcType": "SiemensPlc",
"plcIp": "192.168.2.220",
// "plcIp": "127.0.0.1",
// "plcIp": "127.0.0.1",
"plcPort": 102,
"plcKey": "plc",
"isFlage": true
@ -71,7 +71,8 @@
"isFlage": true
}
],
"redisConfig": "172.16.12.100:6379,password=JyhbRk@2024"
"redisConfig": "172.16.12.100:6379,password=JyhbRk@2024"
// "redisConfig": "175.27.215.92:6379,password=redis@2023"
}
}

@ -35,7 +35,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Generate", "SlnMe
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Other", "Other", "{30102E9A-38CE-4BD6-AA98-98498DE35329}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReadService", "ReadService\ReadService.csproj", "{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReadService", "ReadService\ReadService.csproj", "{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrintBarCode", "PrintBarCode\PrintBarCode.csproj", "{A6C3768F-988A-4AE5-B2CB-A78E25E02F57}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -107,12 +109,17 @@ Global
{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC}.Release|Any CPU.Build.0 = Release|Any CPU
{A6C3768F-988A-4AE5-B2CB-A78E25E02F57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6C3768F-988A-4AE5-B2CB-A78E25E02F57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6C3768F-988A-4AE5-B2CB-A78E25E02F57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6C3768F-988A-4AE5-B2CB-A78E25E02F57}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{19FF8FA9-3FC6-4755-9468-4B66D9D6A7EC} = {30102E9A-38CE-4BD6-AA98-98498DE35329}
{A6C3768F-988A-4AE5-B2CB-A78E25E02F57} = {30102E9A-38CE-4BD6-AA98-98498DE35329}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D414D640-C2DE-44E2-930E-DD095881CDC1}

Loading…
Cancel
Save