diff --git a/PrintBarCode/Business/PrintBusiness.cs b/PrintBarCode/Business/PrintBusiness.cs new file mode 100644 index 0000000..da3434c --- /dev/null +++ b/PrintBarCode/Business/PrintBusiness.cs @@ -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() + { + + } + + + + /// + /// 打印原材料条码方法 + /// + 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("打印错误,检查后请重新操作!"); + } + } + + + + /// + /// 打印成品条码方法 + /// + 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("打印错误,检查后请重新操作!"); + } + } + + + /// + /// 打印配对码方法 + /// + 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("打印错误,检查后请重新操作!"); + } + } + + + + } +} diff --git a/PrintBarCode/DLL/.keep b/PrintBarCode/DLL/.keep new file mode 100644 index 0000000..e69de29 diff --git a/PrintBarCode/DLL/BarcodeStandard.dll b/PrintBarCode/DLL/BarcodeStandard.dll new file mode 100644 index 0000000..4990151 Binary files /dev/null and b/PrintBarCode/DLL/BarcodeStandard.dll differ diff --git a/PrintBarCode/DLL/BinaryKits.Zpl.Label.dll b/PrintBarCode/DLL/BinaryKits.Zpl.Label.dll new file mode 100644 index 0000000..e383c4e Binary files /dev/null and b/PrintBarCode/DLL/BinaryKits.Zpl.Label.dll differ diff --git a/PrintBarCode/DLL/BinaryKits.Zpl.Viewer.dll b/PrintBarCode/DLL/BinaryKits.Zpl.Viewer.dll new file mode 100644 index 0000000..05dcc0c Binary files /dev/null and b/PrintBarCode/DLL/BinaryKits.Zpl.Viewer.dll differ diff --git a/PrintBarCode/DLL/Neodynamic.SDK.ZPLPrinter.dll b/PrintBarCode/DLL/Neodynamic.SDK.ZPLPrinter.dll new file mode 100644 index 0000000..08e0786 Binary files /dev/null and b/PrintBarCode/DLL/Neodynamic.SDK.ZPLPrinter.dll differ diff --git a/PrintBarCode/DLL/QRCoder.dll b/PrintBarCode/DLL/QRCoder.dll new file mode 100644 index 0000000..6cfbf07 Binary files /dev/null and b/PrintBarCode/DLL/QRCoder.dll differ diff --git a/PrintBarCode/DLL/SixLabors.ImageSharp.dll b/PrintBarCode/DLL/SixLabors.ImageSharp.dll new file mode 100644 index 0000000..92a4406 Binary files /dev/null and b/PrintBarCode/DLL/SixLabors.ImageSharp.dll differ diff --git a/PrintBarCode/DLL/SkiaSharp.dll b/PrintBarCode/DLL/SkiaSharp.dll new file mode 100644 index 0000000..a23d166 Binary files /dev/null and b/PrintBarCode/DLL/SkiaSharp.dll differ diff --git a/PrintBarCode/DLL/ZPLPrintDLL.dll b/PrintBarCode/DLL/ZPLPrintDLL.dll new file mode 100644 index 0000000..964dfcc Binary files /dev/null and b/PrintBarCode/DLL/ZPLPrintDLL.dll differ diff --git a/PrintBarCode/DTO/Output.cs b/PrintBarCode/DTO/Output.cs new file mode 100644 index 0000000..d9f47e6 --- /dev/null +++ b/PrintBarCode/DTO/Output.cs @@ -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; } + } +} diff --git a/PrintBarCode/Helper/DebugConfig.cs b/PrintBarCode/Helper/DebugConfig.cs new file mode 100644 index 0000000..4f21434 --- /dev/null +++ b/PrintBarCode/Helper/DebugConfig.cs @@ -0,0 +1,53 @@ + +using System; +using System.Collections.Generic; + +namespace PrintBarCode.Helper +{ + /// + /// 系统配置 + /// + public sealed class DebugConfig + { + private static IniHelper iniHelper = new IniHelper(System.Environment.CurrentDirectory + "/config/App.InI"); + + + private static readonly Lazy lazy = new Lazy(() => new DebugConfig()); + public static DebugConfig Instance + { + get + { + return lazy.Value; + } + } + + public DebugConfig() + { + + } + + + /// + //打印机名称 + /// + public string PrintName + { + get { return iniHelper.IniReadValue("system", "PrintName"); } + set { iniHelper.IniWriteValue("system", "PrintName", value); } + } + + + /// + //所在电脑IP + /// + public string IP + { + get { return iniHelper.IniReadValue("system", "IP"); } + set { iniHelper.IniWriteValue("system", "IP", value); } + } + + + + + } +} diff --git a/PrintBarCode/Helper/IniHelper.cs b/PrintBarCode/Helper/IniHelper.cs new file mode 100644 index 0000000..eae5bc5 --- /dev/null +++ b/PrintBarCode/Helper/IniHelper.cs @@ -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); + + /// + /// 写INI文件 + /// + /// + /// + /// + public void IniWriteValue(string Section, string Key, string Value) + { + + WritePrivateProfileString(Section, Key, Value, this.path); + } + + /// + /// 读取INI文件 + /// + /// + /// + /// + 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; + + } + + + /// + /// 删除ini文件下所有段落 + /// + public void ClearAllSection() + { + IniWriteValue(null, null, null); + } + /// + /// 删除ini文件下personal段落下的所有键 + /// + /// + public void ClearSection(string Section) + { + IniWriteValue(Section, null, null); + } + + public List ReadKeys(String SectionName) + { + return ReadKeys(SectionName, this.path); + } + + public List ReadKeys(string SectionName, string iniFilename) + { + List result = new List(); + 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; + } + } +} diff --git a/PrintBarCode/Helper/JsonParser.cs b/PrintBarCode/Helper/JsonParser.cs new file mode 100644 index 0000000..3de73aa --- /dev/null +++ b/PrintBarCode/Helper/JsonParser.cs @@ -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 ParseJson(string jsonString) + { + try + { + // 解析外层的 JSON 字符串 + var output = JsonSerializer.Deserialize(jsonString); + + // 根据 template 字段选择不同的解析方式 + if (output.Template == "raw") + { + + var rawBarCodeInfoList = JsonSerializer.Deserialize>(output.PrintContent); + return rawBarCodeInfoList.Cast().ToList(); + } + else if (output.Template == "product") + { + + var productBarCodeInfoList = JsonSerializer.Deserialize>(output.PrintContent); + return productBarCodeInfoList.Cast().ToList(); + } + else if(output.Template == "bind") + { + var bindBarCodeInfoList = JsonSerializer.Deserialize>(output.PrintContent); + return bindBarCodeInfoList.Cast().ToList(); + } + else + { + return null; + } + } + catch (JsonException ex) + { + Console.WriteLine($"Failed to parse JSON: {ex.Message}"); + return null; + } + } + } +} diff --git a/PrintBarCode/Helper/NetworkHelper.cs b/PrintBarCode/Helper/NetworkHelper.cs new file mode 100644 index 0000000..50b058d --- /dev/null +++ b/PrintBarCode/Helper/NetworkHelper.cs @@ -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 + { + /// + /// 获取本地计算机的所有 IPv4 地址。 + /// + /// IPv4 地址列表。如果没有找到,则返回一个空列表。 + public static List GetLocalIPv4Addresses() + { + List ipAddresses = new List(); + + 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; + } + + /// + /// 获取本地计算机的第一个有效的 IPv4 地址。 + /// + /// 第一个有效的 IPv4 地址,如果没有找到则返回 null。 + public static string GetFirstLocalIPv4Address() + { + var ipAddresses = GetLocalIPv4Addresses(); + return ipAddresses.Count > 0 ? ipAddresses[0] : null; + } + } +} diff --git a/PrintBarCode/Helper/PrintHelper.cs b/PrintBarCode/Helper/PrintHelper.cs new file mode 100644 index 0000000..eed8185 --- /dev/null +++ b/PrintBarCode/Helper/PrintHelper.cs @@ -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; + } + } +} diff --git a/PrintBarCode/Helper/RawPrinterHelper.cs b/PrintBarCode/Helper/RawPrinterHelper.cs new file mode 100644 index 0000000..a0a8d58 --- /dev/null +++ b/PrintBarCode/Helper/RawPrinterHelper.cs @@ -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; + } + } +} diff --git a/PrintBarCode/MainForm.Designer.cs b/PrintBarCode/MainForm.Designer.cs new file mode 100644 index 0000000..850ecc5 --- /dev/null +++ b/PrintBarCode/MainForm.Designer.cs @@ -0,0 +1,61 @@ +namespace PrintBarCode +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; + } +} \ No newline at end of file diff --git a/PrintBarCode/MainForm.cs b/PrintBarCode/MainForm.cs new file mode 100644 index 0000000..61e9a72 --- /dev/null +++ b/PrintBarCode/MainForm.cs @@ -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(); + + + } + } +} \ No newline at end of file diff --git a/PrintBarCode/MainForm.resx b/PrintBarCode/MainForm.resx new file mode 100644 index 0000000..a395bff --- /dev/null +++ b/PrintBarCode/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PrintBarCode/MessageClient.cs b/PrintBarCode/MessageClient.cs new file mode 100644 index 0000000..739fdf0 --- /dev/null +++ b/PrintBarCode/MessageClient.cs @@ -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("处理消息时发生错误"); + } + } + }); + } + + + + } +} diff --git a/PrintBarCode/Model/BindBarCodeInfo.cs b/PrintBarCode/Model/BindBarCodeInfo.cs new file mode 100644 index 0000000..a0730d5 --- /dev/null +++ b/PrintBarCode/Model/BindBarCodeInfo.cs @@ -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; } + + } +} diff --git a/PrintBarCode/Model/ProductBarCodeInfo.cs b/PrintBarCode/Model/ProductBarCodeInfo.cs new file mode 100644 index 0000000..d6f7a5c --- /dev/null +++ b/PrintBarCode/Model/ProductBarCodeInfo.cs @@ -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; } + + + } +} diff --git a/PrintBarCode/Model/RawBarCodeInfo.cs b/PrintBarCode/Model/RawBarCodeInfo.cs new file mode 100644 index 0000000..dbfd64d --- /dev/null +++ b/PrintBarCode/Model/RawBarCodeInfo.cs @@ -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; } + + } +} diff --git a/PrintBarCode/PrintBarCode.csproj b/PrintBarCode/PrintBarCode.csproj new file mode 100644 index 0000000..a479b7f --- /dev/null +++ b/PrintBarCode/PrintBarCode.csproj @@ -0,0 +1,66 @@ + + + + WinExe + net6.0-windows + enable + true + enable + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + DLL\BarcodeStandard.dll + + + DLL\BinaryKits.Zpl.Label.dll + + + DLL\BinaryKits.Zpl.Viewer.dll + + + DLL\Neodynamic.SDK.ZPLPrinter.dll + + + DLL\QRCoder.dll + + + DLL\SixLabors.ImageSharp.dll + + + DLL\SkiaSharp.dll + + + DLL\ZPLPrintDLL.dll + + + + \ No newline at end of file diff --git a/PrintBarCode/Program.cs b/PrintBarCode/Program.cs new file mode 100644 index 0000000..8b5d01f --- /dev/null +++ b/PrintBarCode/Program.cs @@ -0,0 +1,39 @@ +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Serilog; + +namespace PrintBarCode +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [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(); + }) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +} + +} \ No newline at end of file diff --git a/PrintBarCode/Startup.cs b/PrintBarCode/Startup.cs new file mode 100644 index 0000000..5399054 --- /dev/null +++ b/PrintBarCode/Startup.cs @@ -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 保留所有权利。 +* CLR版本:4.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 +{ + /// + /// + /// + public class Startup + { + /// + /// + /// + /// + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + /// + /// + /// + public IConfiguration Configuration { get; } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// + [Obsolete] + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + + services.AddSingleton(); + services.AddSingleton(); + + //注册AppConfig + services.AddSingleton(provider => + { + var configuration = provider.GetService(); + return configuration.GetSection("AppConfig").Get(); + + }); + + //注册ORM + services.AddSqlSugarSetup(); + + //// 注册 ElectricBusiness + //services.AddScoped(); + + } + + /// + /// AutoFac自动注入 + /// + /// + public void ConfigureContainer(ContainerBuilder builder) + { + DependencyConfigurator.Configure(builder); + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, PrintBarCode.MessageClient messageClient) + { + messageClient.StartListening(); + //启用Serilog中间件 + app.UseSerilogExtensions(); + + + + + } + } +} \ No newline at end of file diff --git a/PrintBarCode/appsettings.json b/PrintBarCode/appsettings.json new file mode 100644 index 0000000..4444f29 --- /dev/null +++ b/PrintBarCode/appsettings.json @@ -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" + + } +} diff --git a/ReadService/MessageClient.cs b/ReadService/MessageClient.cs index 70a5933..ba905fb 100644 --- a/ReadService/MessageClient.cs +++ b/ReadService/MessageClient.cs @@ -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, "处理消息时发生错误"); + // } + //} + + + /// + /// 公共频道 + /// + /// + /// private async void OnMessageReceived(string channel, string message) { - await SpeechStr.Instance.SpeakAsync(message); - Console.WriteLine($"客户端朗读消息{message}"); + await SpeechStr.Instance.SpeakAsync(message); + Console.WriteLine($"客户端公共频道朗读消息{message}"); } - + } } diff --git a/ReadService/appsettings.json b/ReadService/appsettings.json index e413b00..24b4277 100644 --- a/ReadService/appsettings.json +++ b/ReadService/appsettings.json @@ -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" + } } diff --git a/SlnMesnac.Business/MessageService.cs b/SlnMesnac.Business/MessageService.cs index 78657eb..9024ec6 100644 --- a/SlnMesnac.Business/MessageService.cs +++ b/SlnMesnac.Business/MessageService.cs @@ -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; diff --git a/SlnMesnac.Common/GunHelper.cs b/SlnMesnac.Common/GunHelper.cs index ba6af39..007aae2 100644 --- a/SlnMesnac.Common/GunHelper.cs +++ b/SlnMesnac.Common/GunHelper.cs @@ -45,7 +45,6 @@ namespace SlnMesnac.Common { try { - //端口名 注:因为使用的是USB转RS232 所以去设备管理器中查看一下虚拟com口的名字 serialPort.PortName = "COM1";// portName; //波特率 霍尼威尔扫码枪115200,普通9600 diff --git a/SlnMesnac.Config/AppConfig.cs b/SlnMesnac.Config/AppConfig.cs index 82124bf..d955d91 100644 --- a/SlnMesnac.Config/AppConfig.cs +++ b/SlnMesnac.Config/AppConfig.cs @@ -62,6 +62,8 @@ namespace SlnMesnac.Config /// public string redisConfig { get; set; } + + public AppConfig Value => this; } } diff --git a/SlnMesnac.Redis/RedisHandler.cs b/SlnMesnac.Redis/RedisHandler.cs index d0c8a25..ea94ea0 100644 --- a/SlnMesnac.Redis/RedisHandler.cs +++ b/SlnMesnac.Redis/RedisHandler.cs @@ -42,7 +42,7 @@ namespace SlnMesnac.Redis private readonly ISubscriber _subscriber; - private readonly ConnectionMultiplexer redis; + public readonly ConnectionMultiplexer redis; public RedisHandler(AppConfig appConfig, ILogger logger) { @@ -62,11 +62,76 @@ namespace SlnMesnac.Redis /// 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}"); } + + + /// + /// 推送消息到指定工位的队列 + /// + /// 工位ID + /// 消息内容 + 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}"); + } + + + /// + /// 指定工位,从队列中获取一条消息(客户端消费时使用) + /// + /// 工位ID + /// 消息内容,如果没有消息则返回null + 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; + } + + + + /// + /// 确认消息 + /// + /// + public void AcknowledgeMessage(string messageId) + { + var redisDb = redis.GetDatabase(); + redisDb.KeyDelete(messageId); // 删除确认的消息 + _logger.LogInformation($"消息ID:{messageId} 已被确认处理"); + } + + /// /// 订阅消息 /// @@ -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); - } } } diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index a03f043..42bd0dc 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -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" } } diff --git a/SlnMesnac.sln b/SlnMesnac.sln index 0f719af..09146eb 100644 --- a/SlnMesnac.sln +++ b/SlnMesnac.sln @@ -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}