commit 662cefd95db2df3ffe4537e42b387e504624124a Author: wenjy Date: Tue May 28 10:03:54 2024 +0800 添加项目文件。 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Analysis/BufferAnalysis.cs b/SlnMesnac.RfidUpload.Analysis/BufferAnalysis.cs new file mode 100644 index 0000000..5563b16 --- /dev/null +++ b/SlnMesnac.RfidUpload.Analysis/BufferAnalysis.cs @@ -0,0 +1,26 @@ +using System; + +namespace SlnMesnac.RfidUpload.Analysis +{ + /// + /// 标签信息解析 + /// + public sealed class BufferAnalysis + { + #region 单例实现 + private static readonly Lazy _lazy = new Lazy(() => new BufferAnalysis()); + + public static BufferAnalysis Instance + { + get + { + return _lazy.Value; + } + } + #endregion + + private BufferAnalysis() { } + + + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Analysis/InstructionAdapter.cs b/SlnMesnac.RfidUpload.Analysis/InstructionAdapter.cs new file mode 100644 index 0000000..167ee9e --- /dev/null +++ b/SlnMesnac.RfidUpload.Analysis/InstructionAdapter.cs @@ -0,0 +1,85 @@ +using NLog; +using SlnMesnac.RfidUpload.Common; +using SlnMesnac.RfidUpload.Model; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.RfidUpload.Analysis +{ + /// + /// 指令适配器 + /// + public class InstructionAdapter + { + private MsgUtil _msgUtil = MsgUtil.Instance; + private static Logger logger = LogManager.GetCurrentClassLogger(); + #region 单例实现 + private static readonly Lazy _lazy = new Lazy(() => new InstructionAdapter()); + + public static InstructionAdapter Instance + { + get + { + return _lazy.Value; + } + } + #endregion + + private InstructionAdapter() { } + + /// + /// 标签解析 + /// + /// + /// + /// + public InstructionInfo ParseInstruction(byte[] buffer) + { + logger.Info("开始解析标签信息"); + byte[] m_length = new byte[2]; + Array.Copy(buffer, 2, m_length, 0, 2); + int bufferLength = Convert.ToInt32(BitConverter.ToString(m_length).Replace("-", ""), 16); + + if (buffer.Length != bufferLength) + { + throw new ArgumentException("指令长度不正确"); + } + + byte[] xorbuffer = new byte[buffer.Length - 3]; + Array.Copy(buffer, 2, xorbuffer, 0, xorbuffer.Length); + string xorStr = _msgUtil.CalculateXORChecksum(xorbuffer); + string bufferXor = buffer[buffer.Length - 1].ToString("X2"); + if (bufferXor != xorStr) + { + throw new ArgumentException($"XOR校验失败,指令XOR:{bufferXor},计算XOR:{xorStr}"); + } + + InstructionInfo instructionInfo = new InstructionInfo(); + byte[] m_stx = new byte[2]; + Array.Copy(buffer, 0, m_stx, 0, 2); + instructionInfo.stx = BitConverter.ToString(m_stx).Replace("-", ""); + + instructionInfo.len = bufferLength; + + instructionInfo.cmd = buffer[4]; + + int status = Convert.ToInt32(buffer[5]); + instructionInfo.status = status; + + byte[] m_data = new byte[bufferLength - 7]; + Array.Copy(buffer, 6, m_data, 0, m_data.Length); + string dataValue = Encoding.ASCII.GetString(m_data); + instructionInfo.data = dataValue; + + instructionInfo.xor = buffer[buffer.Length - 1]; + + instructionInfo.recordtime = DateTime.Now; + + return instructionInfo; + } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Analysis/SlnMesnac.RfidUpload.Analysis.csproj b/SlnMesnac.RfidUpload.Analysis/SlnMesnac.RfidUpload.Analysis.csproj new file mode 100644 index 0000000..5054813 --- /dev/null +++ b/SlnMesnac.RfidUpload.Analysis/SlnMesnac.RfidUpload.Analysis.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.1 + enable + + + + + + + + + diff --git a/SlnMesnac.RfidUpload.Business/HandleBusiness.cs b/SlnMesnac.RfidUpload.Business/HandleBusiness.cs new file mode 100644 index 0000000..1424a1d --- /dev/null +++ b/SlnMesnac.RfidUpload.Business/HandleBusiness.cs @@ -0,0 +1,163 @@ +using SlnMesnac.RfidUpload.Analysis; +using SlnMesnac.RfidUpload.Common; +using SlnMesnac.RfidUpload.Model; +using SlnMesnac.RfidUpload.TouchSocket; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SlnMesnac.RfidUpload.Business +{ + /// + /// 业务逻辑处理 + /// + public class HandleBusiness + { + private JsonChange _jsonChange = JsonChange.Instance; + private InstructionAdapter adapter = InstructionAdapter.Instance; + private WebApiClientApp _webApiClientApp = WebApiClientApp.Instance; + + private List instructionInfoList = new List(); + + #region 单例实现 + private static readonly Lazy _lazy = new Lazy(() => new HandleBusiness()); + + public static HandleBusiness Instance + { + get + { + return _lazy.Value; + } + } + #endregion + + #region 委托事件 + + /// + /// 刷新标签解析 + /// + public delegate void RefreshInstructionInfoDataGrid(InstructionInfo instructionInfo); + public event RefreshInstructionInfoDataGrid InstructionInfoDataGridEvent; + + /// + /// 刷新日志内容 + /// + public delegate void RefreshLogMessage(string message); + public event RefreshLogMessage RefreshLogMessageEvent; + + #endregion + + private HandleBusiness() { } + + + + /// + /// 标签处理 + /// + /// + /// + public void LabelHandle(byte[] buffer) + { + //功能码判断 + if (buffer[4] == 0x31) + { + try + { + InstructionInfo info = adapter.ParseInstruction(buffer); + + if (info != null) + { + if (FilterTags(info)) + { + instructionInfoList.Add(info); + RefreshLogMessageEvent?.Invoke($"标签解析数据:{_jsonChange.ModeToJson(info)}"); + + InstructionInfoDataGridEvent?.Invoke(info); + } + else + { + RefreshLogMessageEvent?.Invoke($"标签:{info.data};与前次读取间隔小于1分钟,不进行逻辑处理"); + } + } + } + catch (Exception e) + { + RefreshLogMessageEvent?.Invoke($"标签解析异常:{e.Message}"); + } + + } + } + + /// + /// 粘包处理 + /// + /// + /// + public List SplitPackets(byte[] receivedData) + { + List packets = new List(); + int index = 0; + while (index < receivedData.Length) + { + if (receivedData[index] == 0xAA && receivedData[index + 1] == 0x55) + { + int packetLength = (receivedData[index + 2] << 8) | receivedData[index + 3]; + if (packetLength <= receivedData.Length - index) + { + byte[] packet = new byte[packetLength]; + Array.Copy(receivedData, index, packet, 0, packetLength); + packets.Add(packet); + index += packetLength; + } + else + { + break; + } + } + else + { + index++; + } + } + return packets; + } + + public void apiTest(string url) + { + //WebApiClientApp api = new WebApiClientApp(); + _webApiClientApp.Upload(url); + } + + /// + /// 标签过滤:同一标签1分钟内不进行逻辑处理 + /// + /// + /// + private bool FilterTags(InstructionInfo instructionInfo) + { + + InstructionInfo lastInstructionInfo = instructionInfoList.Where(x => x.data == instructionInfo.data).FirstOrDefault(); + + if(lastInstructionInfo == null) + { + return true; + } + else + { + TimeSpan timeDifference = instructionInfo.recordtime.Subtract(lastInstructionInfo.recordtime); + double minutesDifference = timeDifference.TotalMinutes; + + if (minutesDifference < 1) + { + return false; + } + else + { + instructionInfoList.Remove(lastInstructionInfo); + return true; + } + } + + } + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Business/SerialPortBusiness.cs b/SlnMesnac.RfidUpload.Business/SerialPortBusiness.cs new file mode 100644 index 0000000..67645a8 --- /dev/null +++ b/SlnMesnac.RfidUpload.Business/SerialPortBusiness.cs @@ -0,0 +1,124 @@ +using System; +using System.IO.Ports; +using System.Linq; +using System.Threading; + +namespace SlnMesnac.RfidUpload.Business +{ + /// + /// 串口通讯类 + /// + public class SerialPortBusiness + { + + #region 单例实现 + private static readonly Lazy _lazy = new Lazy(() => new SerialPortBusiness()); + + public static SerialPortBusiness Instance + { + get + { + return _lazy.Value; + } + } + #endregion + + #region 委托事件 + + /// + /// 刷新标签解析 + /// + public delegate void ReceivedData(byte[] buffer); + public event ReceivedData ReceivedDataEvent; + + /// + /// 刷新日志内容 + /// + public delegate void RefreshLogMessage(string message); + public event RefreshLogMessage RefreshLogMessageEvent; + + #endregion + + private SerialPort _serialPort; + + private SerialPortBusiness() + { + + } + + /// + /// 打开串口 + /// + public void Open() + { + string port = System.IO.Ports.SerialPort.GetPortNames().FirstOrDefault(); + _serialPort = new SerialPort(port, 115200, Parity.None, 8, StopBits.One); + _serialPort.DataReceived += SerialPortDataReceived; + + _serialPort.Open(); + } + + /// + /// 关闭串口 + /// + public void Close() + { + if (_serialPort != null) + { + _serialPort.Close(); + } + else + { + throw new ArgumentException("_serialPort == null"); + } + } + + /// + /// 接收数据 + /// + /// + /// + private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) + { + try + { + Thread.Sleep(200); + int bytesToRead = _serialPort.BytesToRead; + byte[] buffer = new byte[bytesToRead]; + + _serialPort.Read(buffer, 0, bytesToRead); + + RefreshLogMessageEvent?.Invoke("Received data: " + BitConverter.ToString(buffer).Replace("-", " ")); + + if (CheckReceivedData(buffer)) + { + ReceivedDataEvent?.Invoke(buffer); + } + else + { + RefreshLogMessageEvent?.Invoke("心跳指令不进行逻辑处理"); + } + } + catch (Exception ex) + { + RefreshLogMessageEvent?.Invoke($"接收数据异常:{ex.Message}"); + } + } + + /// + /// 判断是否为业务数据 + /// + /// + /// + private bool CheckReceivedData(byte[] data) + { + + if (data.Length > 4) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Business/SlnMesnac.RfidUpload.Business.csproj b/SlnMesnac.RfidUpload.Business/SlnMesnac.RfidUpload.Business.csproj new file mode 100644 index 0000000..c86fc79 --- /dev/null +++ b/SlnMesnac.RfidUpload.Business/SlnMesnac.RfidUpload.Business.csproj @@ -0,0 +1,18 @@ + + + + netstandard2.1 + enable + + + + + + + + + + + + + diff --git a/SlnMesnac.RfidUpload.Common/JsonChange.cs b/SlnMesnac.RfidUpload.Common/JsonChange.cs new file mode 100644 index 0000000..c18ab1f --- /dev/null +++ b/SlnMesnac.RfidUpload.Common/JsonChange.cs @@ -0,0 +1,109 @@ +using Nancy.Json; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace SlnMesnac.RfidUpload.Common +{ + public sealed class JsonChange + { + + private static readonly Lazy lazy = new Lazy(() => new JsonChange()); + + public static JsonChange Instance + { + get + { + return lazy.Value; + } + } + + private JsonChange() { } + + /// + /// Model 实体转json + /// + /// 可以是单个实体,也可是实体集(即:ToList()) + /// + public string ModeToJson(object Model) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + try + { + string str = serializer.Serialize(Model); + return str; + } + catch (Exception) + { + return ""; + } + } + + /// + /// json实体转Model + /// + /// + /// + /// + public T JsonToMode(string jsonStr) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + try + { + var info = serializer.Deserialize(jsonStr); + return info; + } + catch (Exception) + { + return default(T); + } + } + + /// + /// object转dictionary + /// + /// + /// + public Dictionary objectToDictionary(string jsonData) + { + Dictionary result = new Dictionary(); + + var inf = JsonConvert.DeserializeObject>(jsonData); + + foreach (KeyValuePair item in inf) + { + if (item.Value != null) + { + var type = item.Value.GetType(); + if (type == typeof(JObject)) + { + var info = objectToDictionary(JsonConvert.SerializeObject(item.Value)); + foreach (KeyValuePair ite in info) + { + result.Add(ite.Key, ite.Value); + } + continue; + } + else if (type == typeof(JArray)) + { + JArray array = (JArray)item.Value; + var info = objectToDictionary(JsonConvert.SerializeObject(array[0])); + foreach (KeyValuePair ite in info) + { + result.Add(item.Key + ite.Key, ite.Value); + } + continue; + } + } + + result.Add(item.Key, item.Value); + } + + return result; + } + + + + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Common/MsgUtil.cs b/SlnMesnac.RfidUpload.Common/MsgUtil.cs new file mode 100644 index 0000000..d628608 --- /dev/null +++ b/SlnMesnac.RfidUpload.Common/MsgUtil.cs @@ -0,0 +1,309 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SlnMesnac.RfidUpload.Common +{ + /// + /// 工具类 + /// + public sealed class MsgUtil + { + + private static readonly Lazy lazy = new Lazy(() => new MsgUtil()); + + public static MsgUtil Instance + { + get + { + return lazy.Value; + } + } + + private MsgUtil() { } + + #region 数据解析公共方法 + /// + /// 字节数组转换成结构体 + /// + /// + /// + /// + /// + public static object BytesToStruct(byte[] buf, int len, Type type) + { + object rtn; + IntPtr buffer = Marshal.AllocHGlobal(len); + Marshal.Copy(buf, 0, buffer, len); + try + { + rtn = Marshal.PtrToStructure(buffer, type); + Marshal.FreeHGlobal(buffer); + } + catch (Exception) + { + return null; + } + return rtn; + } + + public string StringToHexString(string s, Encoding encode) + { + + byte[] b = encode.GetBytes(s); //按照指定编码将string编程字节数组 + string result = string.Empty; + for (int i = 0; i < b.Length; i++) //逐字节变为16进制字符,以%隔开 + { + result += "%" + Convert.ToString(b[i], 16); + } + return result; + } + + //// + /// 结构体转byte数组 + /// + /// 要转换的结构体 + /// 转换后的byte数组 + public static byte[] StructToBytes(object structObj) + { + //得到结构体的大小 + int size = Marshal.SizeOf(structObj); + //创建byte数组 + byte[] bytes = new byte[size]; + //分配结构体大小的内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + //将结构体拷到分配好的内存空间 + Marshal.StructureToPtr(structObj, structPtr, false); + //从内存空间拷到byte数组 + Marshal.Copy(structPtr, bytes, 0, size); + //释放内存空间 + Marshal.FreeHGlobal(structPtr); + //返回byte数组 + return bytes; + } + + + #endregion + #region 消息验证方法 + + /// + /// CS和校验 + /// + /// + /// + public byte Check_CS(byte[] Abyte) + { + byte result = new byte(); + try + { + int num = 0; + for (int i = 0; i < Abyte.Length; i++) + { + num = (num + Abyte[i]) % 256; + } + result = (byte)num; + } + catch + { + result = 0; + } + return result; + } + + /// + /// BCC异或取反校验 + /// + /// + /// + public string getBCC(byte[] data) + { + String ret = ""; + byte[] BCC = new byte[1]; + for (int i = 0; i < data.Length; i++) + { + BCC[0] = (byte)(BCC[0] ^ data[i]); + } + String hex = ((~BCC[0]) & 0xFF).ToString("X");//取反操作 + if (hex.Length == 1) + { + hex = '0' + hex; + } + ret += hex.ToUpper(); + return ret; + } + + static int BytesToInt(byte[] b, int length) + { + int temp = 0; + for (int i = 0; i <= length - 1 && i < 4; i++) + { + temp += (int)(b[i] << (i * 8)); + } + return temp; + } + + public static byte[] CalculateVerify(byte[] pMessage, int iLength) + { + UInt16 i; + int iVerify = 0; + + iVerify = pMessage[0]; + for (i = 0; i < iLength - 1; i++) + { + iVerify = iVerify + pMessage[i + 1]; + } + return BitConverter.GetBytes(Convert.ToUInt16(iVerify)); + } + #endregion + public byte[] HexStrTorbytes(string strHex)//e.g. " 01 01" ---> { 0x01, 0x01} + { + strHex = strHex.Replace(" ", ""); + if ((strHex.Length % 2) != 0) + strHex += " "; + byte[] returnBytes = new byte[strHex.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + returnBytes[i] = Convert.ToByte(strHex.Substring(i * 2, 2), 16); + return returnBytes; + } + + /// + /// 将字符串强制转换成int,转换失败则返回0 + /// + /// + /// + public int ParseToInt(string str) + { + int returnInt = 0; + + if (str == null || str.Trim().Length < 1) + { + return returnInt; + } + + if (int.TryParse(str, out returnInt)) + { + return returnInt; + } + else + { + return 0; + } + } + + public byte[] HexToString(string Str) + { + byte[] str = new byte[Str.Length / 2]; + for (int i = 0; i < str.Length; i++) + { + int temp = Convert.ToInt32(Str.Substring(i * 2, 2), 16); + str[i] = (byte)temp; + } + return str; + } + public string ConverToString(byte[] data) + { + string str; + StringBuilder stb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + if ((int)data[i] > 15) + { + stb.Append(Convert.ToString(data[i], 16).ToUpper()); //添加字符串 + } + else //如果是小于0F需要加个零 + { + stb.Append("0" + Convert.ToString(data[i], 16).ToUpper()); + } + } + str = stb.ToString(); + return str; + } + + public string bytesToHexStr(byte[] bytes, int iLen) + { + StringBuilder sb = new StringBuilder(); + if (bytes != null) + { + for (int i = 0; i < iLen; i++) + { + sb.Append(bytes[i].ToString("X2")); + } + } + return sb.ToString(); + } + + /// + /// 从十进制转换到十六进制 + /// + /// + /// + public string Ten2Hex(string ten) + { + ulong tenValue = Convert.ToUInt64(ten); + ulong divValue, resValue; + string hex = ""; + do + { + //divValue = (ulong)Math.Floor(tenValue / 16); + + divValue = (ulong)Math.Floor((decimal)(tenValue / 16)); + + resValue = tenValue % 16; + hex = tenValue2Char(resValue) + hex; + tenValue = divValue; + } + while (tenValue >= 16); + if (tenValue != 0) + hex = tenValue2Char(tenValue) + hex; + return hex; + } + + /// + /// 异或和校验 + /// + /// + /// + public string CalculateXORChecksum(byte[] bytes) + { + byte checksum = bytes[0]; + foreach (byte b in bytes) + { + checksum ^= b; + } + + return checksum.ToString("X2"); + } + + public string tenValue2Char(ulong ten) + { + switch (ten) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + return ten.ToString(); + case 10: + return "A"; + case 11: + return "B"; + case 12: + return "C"; + case 13: + return "D"; + case 14: + return "E"; + case 15: + return "F"; + default: + return ""; + } + } + } +} diff --git a/SlnMesnac.RfidUpload.Common/SlnMesnac.RfidUpload.Common.csproj b/SlnMesnac.RfidUpload.Common/SlnMesnac.RfidUpload.Common.csproj new file mode 100644 index 0000000..0ca18b0 --- /dev/null +++ b/SlnMesnac.RfidUpload.Common/SlnMesnac.RfidUpload.Common.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.1 + enable + + + + + + + + diff --git a/SlnMesnac.RfidUpload.Config/AppConfig.cs b/SlnMesnac.RfidUpload.Config/AppConfig.cs new file mode 100644 index 0000000..bb3722f --- /dev/null +++ b/SlnMesnac.RfidUpload.Config/AppConfig.cs @@ -0,0 +1,28 @@ +using System; +using Microsoft.Extensions.Options; + +namespace SlnMesnac.RfidUpload.Config +{ + /// + /// 系统配置 + /// + public class AppConfig : IOptions + { + /// + /// 日志文件路径 + /// + public string logPath { get; set; } + + /// + /// MES 数据库连接字符串 + /// + public string mesConnStr { get; set; } + + /// + /// MCS 数据库连接字符串 + /// + public string mcsConnStr { get; set; } + + public AppConfig Value => this; + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Config/SlnMesnac.RfidUpload.Config.csproj b/SlnMesnac.RfidUpload.Config/SlnMesnac.RfidUpload.Config.csproj new file mode 100644 index 0000000..d6ef7df --- /dev/null +++ b/SlnMesnac.RfidUpload.Config/SlnMesnac.RfidUpload.Config.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.1 + enable + + + + + + + diff --git a/SlnMesnac.RfidUpload.Model/ContainerInbound.cs b/SlnMesnac.RfidUpload.Model/ContainerInbound.cs new file mode 100644 index 0000000..a65c893 --- /dev/null +++ b/SlnMesnac.RfidUpload.Model/ContainerInbound.cs @@ -0,0 +1,43 @@ +namespace SlnMesnac.RfidUpload.Model +{ + /// + /// 容器入库 + /// + public class ContainerInbound + { + /// + /// 入参1,请求报文到消息头 + /// + public string messageHeader { get; set; } + + /// + /// 入参2,将下列参数封装到batchOpenQuery + /// + public string batchOpenQuery { get; set; } + + /// + /// 机构代码 + /// + public string opOrgCode { get; set; } + + /// + /// 登录人代码 + /// + public string userCode { get; set; } + + /// + /// 登录人名称 + /// + public string userName { get; set; } + + /// + /// 省份代码 + /// + public string province { get; set; } + + /// + /// 容器条码 + /// + public string rqtm { get; set; } + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Model/ContainerSealed.cs b/SlnMesnac.RfidUpload.Model/ContainerSealed.cs new file mode 100644 index 0000000..d786e35 --- /dev/null +++ b/SlnMesnac.RfidUpload.Model/ContainerSealed.cs @@ -0,0 +1,83 @@ +namespace SlnMesnac.RfidUpload.Model +{ + /// + /// 容器封发扫描 + /// + public class ContainerSealed + { + /// + /// 入参1,请求报文到消息头 + /// + public string messageHeader { get; set; } + + /// + /// 入参2,将下列参数封装到containerRegisterQuery + /// + public string containerRegisterQuery { get; set; } + + /// + /// 机构代码 + /// + public string opOrgCode { get; set; } + + /// + /// 机构名称 + /// + public string opOrgName { get; set; } + + /// + /// 登录人代码 + /// + public string userCode { get; set; } + + /// + /// 登录人名称 + /// + public string userName { get; set; } + + /// + /// 省份代码 + /// + public string province { get; set; } + + /// + /// 容器种类名称 + /// + public string rqzlmc { get; set; } + + /// + /// 总包Id + /// + public string zbid { get; set; } + + /// + /// 寄达局名称 + /// + public string destinationOrgName { get; set; } + + /// + /// 寄达局编号 + /// + public string destinationOrgCode { get; set; } + + /// + /// 容器种类 + /// + public string rqzl { get; set; } + + /// + /// 容器型号 + /// + public string rqxh { get; set; } + + /// + /// 容器型号名称 + /// + public string rqxhmc { get; set; } + + /// + /// 容器条码 + /// + public string rqtm { get; set; } + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Model/InstructionInfo.cs b/SlnMesnac.RfidUpload.Model/InstructionInfo.cs new file mode 100644 index 0000000..cdc427d --- /dev/null +++ b/SlnMesnac.RfidUpload.Model/InstructionInfo.cs @@ -0,0 +1,55 @@ +using MiniExcelLibs.Attributes; +using System; + +namespace SlnMesnac.RfidUpload.Model +{ + /// + /// 指令信息 + /// + public class InstructionInfo + { + /// + /// + /// + [ExcelColumn(Name = "stx",Index = 0),ExcelColumnWidth(23)] + public string stx { get; set; } + + /// + /// 报文长度,包含帧头、校验 + /// + [ExcelColumn(Name = "len", Index = 1), ExcelColumnWidth(23)] + public int len { get; set; } + + /// + /// 报文类型0x31 + /// + [ExcelColumn(Name = "cmd", Index = 2), ExcelColumnWidth(23)] + public byte cmd { get; set; } + + /// + /// 擦除状态:0-成功;1-失败 + /// + [ExcelColumn(Name = "status", Index = 3), ExcelColumnWidth(23)] + public int status { get; set; } + + /// + /// 数据 + /// + [ExcelColumn(Name = "data", Index = 4), ExcelColumnWidth(53)] + public string data { get; set; } + + /// + /// 异或和校验,10进制 + /// + [ExcelColumn(Name = "xor", Index = 5), ExcelColumnWidth(23)] + public byte xor { get; set; } + + /// + /// 记录时间 + /// + [ExcelColumn(Name = "recordtime", Index = 6), ExcelColumnWidth(23)] + public DateTime recordtime { get; set; } + + + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.Model/SlnMesnac.RfidUpload.Model.csproj b/SlnMesnac.RfidUpload.Model/SlnMesnac.RfidUpload.Model.csproj new file mode 100644 index 0000000..89c6484 --- /dev/null +++ b/SlnMesnac.RfidUpload.Model/SlnMesnac.RfidUpload.Model.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.1 + enable + + + + + + + diff --git a/SlnMesnac.RfidUpload.NLog/SlnMesnac.RfidUpload.NLog.csproj b/SlnMesnac.RfidUpload.NLog/SlnMesnac.RfidUpload.NLog.csproj new file mode 100644 index 0000000..c615582 --- /dev/null +++ b/SlnMesnac.RfidUpload.NLog/SlnMesnac.RfidUpload.NLog.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.1 + enable + + + + + + + + + + + + + + + + + + + + diff --git a/SlnMesnac.RfidUpload.TouchSocket/SlnMesnac.RfidUpload.TouchSocket.csproj b/SlnMesnac.RfidUpload.TouchSocket/SlnMesnac.RfidUpload.TouchSocket.csproj new file mode 100644 index 0000000..c0915eb --- /dev/null +++ b/SlnMesnac.RfidUpload.TouchSocket/SlnMesnac.RfidUpload.TouchSocket.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.1 + enable + + + + + + + + + + + diff --git a/SlnMesnac.RfidUpload.TouchSocket/WebApiClientApp.cs b/SlnMesnac.RfidUpload.TouchSocket/WebApiClientApp.cs new file mode 100644 index 0000000..c727b69 --- /dev/null +++ b/SlnMesnac.RfidUpload.TouchSocket/WebApiClientApp.cs @@ -0,0 +1,57 @@ +using SlnMesnac.RfidUpload.Model; +using System; +using TouchSocket.Rpc.WebApi; + +namespace SlnMesnac.RfidUpload.TouchSocket +{ + public sealed class WebApiClientApp + { + + #region 单例实现 + private static readonly Lazy _lazy = new Lazy(() => new WebApiClientApp()); + + public static WebApiClientApp Instance + { + get + { + return _lazy.Value; + } + } + #endregion + + private WebApiClientApp() { } + + private WebApiClient CreateWebApiClient(string url) + { + WebApiClient client = new WebApiClient(); + client.Setup(url); + client.Connect(); + Console.WriteLine("连接成功"); + return client; + } + + public void Upload(string url) + { + try + { + var client = CreateWebApiClient(url); + + var param = new ContainerInbound() + { + messageHeader = Guid.NewGuid().ToString(), + batchOpenQuery = "OK", + opOrgCode = Guid.NewGuid().ToString() + }; + + var sum2 = client.Invoke("POST:/Server/ContainerInboundApi", null, param); + Console.WriteLine($"Post调用成功,结果:{sum2.Message}"); + + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + + } + } +} \ No newline at end of file diff --git a/SlnMesnac.RfidUpload.UI/App.xaml b/SlnMesnac.RfidUpload.UI/App.xaml new file mode 100644 index 0000000..69de2e8 --- /dev/null +++ b/SlnMesnac.RfidUpload.UI/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/SlnMesnac.RfidUpload.UI/App.xaml.cs b/SlnMesnac.RfidUpload.UI/App.xaml.cs new file mode 100644 index 0000000..3533401 --- /dev/null +++ b/SlnMesnac.RfidUpload.UI/App.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows; + +namespace SlnMesnac.RfidUpload.UI +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/SlnMesnac.RfidUpload.UI/AssemblyInfo.cs b/SlnMesnac.RfidUpload.UI/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/SlnMesnac.RfidUpload.UI/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/SlnMesnac.RfidUpload.UI/MainWindow.xaml b/SlnMesnac.RfidUpload.UI/MainWindow.xaml new file mode 100644 index 0000000..45af2cc --- /dev/null +++ b/SlnMesnac.RfidUpload.UI/MainWindow.xaml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + +