From f541d26955098bb625eddfbf7243fbaa46bf32c0 Mon Sep 17 00:00:00 2001 From: hehaoyang Date: Wed, 18 Oct 2023 23:43:19 +0800 Subject: [PATCH] V1.1.0 --- .gitignore | 271 ++++++++ PrinterClient/AutoUpgrade/AutoUpgrade.csproj | 15 + PrinterClient/AutoUpgrade/Program.cs | 93 +++ PrinterClient/PrinterClient.sln | 31 + PrinterClient/PrinterClient/BoxServer.cs | 620 ++++++++++++++++++ PrinterClient/PrinterClient/DebugTool.cs | 135 ++++ .../PrinterClient/PrinterClient.csproj | 56 ++ PrinterClient/PrinterClient/Program.cs | 72 ++ PrinterClient/PrinterClient/RX1/CyStatus.cs | 317 +++++++++ PrinterClient/PrinterClient/ReadMe.cs | 96 +++ PrinterClient/PrinterClient/TaskDispatcher.cs | 485 ++++++++++++++ .../PrinterClient/Utils/ByteUtils.cs | 30 + .../PrinterClient/Utils/DeviceUtils.cs | 23 + .../PrinterClient/Utils/FileUtils.cs | 74 +++ PrinterClient/PrinterClient/Utils/LogUtils.cs | 44 ++ .../PrinterClient/Utils/TimerUtils.cs | 38 ++ PrinterClient/PrinterClient/app.config | 9 + PrinterClient/PrinterClient/protocol.cs | 351 ++++++++++ .../物联平台-终端打印盒子TCP协议V1.0.4.docx | Bin 0 -> 43161 bytes TestView/TestView.sln | 25 + TestView/TestView/App.config | 6 + TestView/TestView/App.xaml | 9 + TestView/TestView/App.xaml.cs | 17 + TestView/TestView/FodyWeavers.xml | 2 + TestView/TestView/FodyWeavers.xsd | 141 ++++ TestView/TestView/Loading.xaml | 99 +++ TestView/TestView/Loading.xaml.cs | 28 + TestView/TestView/MainWindow.xaml | 90 +++ TestView/TestView/MainWindow.xaml.cs | 68 ++ TestView/TestView/Properties/AssemblyInfo.cs | 55 ++ .../TestView/Properties/Resources.Designer.cs | 63 ++ TestView/TestView/Properties/Resources.resx | 117 ++++ .../TestView/Properties/Settings.Designer.cs | 26 + .../TestView/Properties/Settings.settings | 7 + TestView/TestView/TaskDispatcher.cs | 383 +++++++++++ TestView/TestView/TaskInfoWindow.xaml | 52 ++ TestView/TestView/TaskInfoWindow.xaml.cs | 58 ++ TestView/TestView/TestView.csproj | 122 ++++ TestView/TestView/packages.config | 4 + 39 files changed, 4132 insertions(+) create mode 100644 .gitignore create mode 100644 PrinterClient/AutoUpgrade/AutoUpgrade.csproj create mode 100644 PrinterClient/AutoUpgrade/Program.cs create mode 100644 PrinterClient/PrinterClient.sln create mode 100644 PrinterClient/PrinterClient/BoxServer.cs create mode 100644 PrinterClient/PrinterClient/DebugTool.cs create mode 100644 PrinterClient/PrinterClient/PrinterClient.csproj create mode 100644 PrinterClient/PrinterClient/Program.cs create mode 100644 PrinterClient/PrinterClient/RX1/CyStatus.cs create mode 100644 PrinterClient/PrinterClient/ReadMe.cs create mode 100644 PrinterClient/PrinterClient/TaskDispatcher.cs create mode 100644 PrinterClient/PrinterClient/Utils/ByteUtils.cs create mode 100644 PrinterClient/PrinterClient/Utils/DeviceUtils.cs create mode 100644 PrinterClient/PrinterClient/Utils/FileUtils.cs create mode 100644 PrinterClient/PrinterClient/Utils/LogUtils.cs create mode 100644 PrinterClient/PrinterClient/Utils/TimerUtils.cs create mode 100644 PrinterClient/PrinterClient/app.config create mode 100644 PrinterClient/PrinterClient/protocol.cs create mode 100644 PrinterClient/物联平台-终端打印盒子TCP协议V1.0.4.docx create mode 100644 TestView/TestView.sln create mode 100644 TestView/TestView/App.config create mode 100644 TestView/TestView/App.xaml create mode 100644 TestView/TestView/App.xaml.cs create mode 100644 TestView/TestView/FodyWeavers.xml create mode 100644 TestView/TestView/FodyWeavers.xsd create mode 100644 TestView/TestView/Loading.xaml create mode 100644 TestView/TestView/Loading.xaml.cs create mode 100644 TestView/TestView/MainWindow.xaml create mode 100644 TestView/TestView/MainWindow.xaml.cs create mode 100644 TestView/TestView/Properties/AssemblyInfo.cs create mode 100644 TestView/TestView/Properties/Resources.Designer.cs create mode 100644 TestView/TestView/Properties/Resources.resx create mode 100644 TestView/TestView/Properties/Settings.Designer.cs create mode 100644 TestView/TestView/Properties/Settings.settings create mode 100644 TestView/TestView/TaskDispatcher.cs create mode 100644 TestView/TestView/TaskInfoWindow.xaml create mode 100644 TestView/TestView/TaskInfoWindow.xaml.cs create mode 100644 TestView/TestView/TestView.csproj create mode 100644 TestView/TestView/packages.config diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74b8f27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,271 @@ +其他资料/gcm.zip +其他资料/Lubuntu_1404_For_OrangePiPC_v0_8_0_.img.zip +其他资料/protocol.proto +其他资料/prototobuf/build.bat +其他资料/prototobuf/protobuf-net.dll +其他资料/prototobuf/protobuf-net.Reflection.dll +其他资料/prototobuf/protoc.exe +其他资料/prototobuf/protocol.cs +其他资料/prototobuf/protocol.proto +其他资料/prototobuf/protogen.exe +其他资料/win32_disk_imager/Changelog.txt +其他资料/win32_disk_imager/D3Dcompiler_47.dll +其他资料/win32_disk_imager/GPL-2 +其他资料/win32_disk_imager/LGPL-2.1 +其他资料/win32_disk_imager/libEGL.dll +其他资料/win32_disk_imager/libgcc_s_dw2-1.dll +其他资料/win32_disk_imager/libGLESV2.dll +其他资料/win32_disk_imager/libstdc++-6.dll +其他资料/win32_disk_imager/libwinpthread-1.dll +其他资料/win32_disk_imager/opengl32sw.dll +其他资料/win32_disk_imager/Qt5Core.dll +其他资料/win32_disk_imager/Qt5Gui.dll +其他资料/win32_disk_imager/Qt5Svg.dll +其他资料/win32_disk_imager/Qt5Widgets.dll +其他资料/win32_disk_imager/README.txt +其他资料/win32_disk_imager/Win32DiskImager.exe +其他资料/win32_disk_imager/platforms/qwindows.dll +其他资料/win32_disk_imager/translations/diskimager_de.qm +其他资料/win32_disk_imager/translations/diskimager_es.qm +其他资料/win32_disk_imager/translations/diskimager_fr.qm +其他资料/win32_disk_imager/translations/diskimager_it.qm +其他资料/win32_disk_imager/translations/diskimager_nl.qm +其他资料/win32_disk_imager/translations/diskimager_pl.qm +其他资料/win32_disk_imager/translations/diskimager_ta_IN.qm +其他资料/win32_disk_imager/translations/diskimager_zh_CN.qm +其他资料/win32_disk_imager/translations/diskimager_zh_TW.qm +其他资料/win32_disk_imager/translations/qt_ca.qm +其他资料/win32_disk_imager/translations/qt_cs.qm +其他资料/win32_disk_imager/translations/qt_de.qm +其他资料/win32_disk_imager/translations/qt_en.qm +其他资料/win32_disk_imager/translations/qt_fi.qm +其他资料/win32_disk_imager/translations/qt_fr.qm +其他资料/win32_disk_imager/translations/qt_he.qm +其他资料/win32_disk_imager/translations/qt_hu.qm +其他资料/win32_disk_imager/translations/qt_it.qm +其他资料/win32_disk_imager/translations/qt_ja.qm +其他资料/win32_disk_imager/translations/qt_ko.qm +其他资料/win32_disk_imager/translations/qt_lv.qm +其他资料/win32_disk_imager/translations/qt_pl.qm +其他资料/win32_disk_imager/translations/qt_ru.qm +其他资料/win32_disk_imager/translations/qt_sk.qm +其他资料/win32_disk_imager/translations/qt_uk.qm +TestView/.vs/TestView/FileContentIndex/5c1e8809-58e8-4f8d-9995-548a206fd26c.vsidx +TestView/.vs/TestView/FileContentIndex/read.lock +TestView/.vs/TestView/v17/.suo +PrinterClient/.vs/PrinterClient/DesignTimeBuild/.dtbcache.v2 +PrinterClient/.vs/PrinterClient/FileContentIndex/b9d10d80-0d83-471f-a7e3-ffbdd3b3b617.vsidx +PrinterClient/.vs/PrinterClient/v17/.futdcache.v1 +PrinterClient/.vs/PrinterClient/v17/.futdcache.v2 +PrinterClient/.vs/PrinterClient/v17/.suo +PrinterClient/.vs/PrinterClient/xs/UserPrefs.xml +PrinterClient/.vs/PrinterClient/xs/project-cache/AutoUpgrade-Debug.json +PrinterClient/.vs/PrinterClient/xs/project-cache/PrinterClient-Debug.json +PrinterClient/.vs/ProjectEvaluation/printerclient.metadata.v7.bin +PrinterClient/.vs/ProjectEvaluation/printerclient.projects.v7.bin +PrinterClient/.vscode/settings.json +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.deps.json +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.dll +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.exe +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.pdb +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.runtimeconfig.dev.json +PrinterClient/AutoUpgrade/bin/Debug/netcoreapp3.1/AutoUpgrade.runtimeconfig.json +PrinterClient/AutoUpgrade/obj/AutoUpgrade.csproj.nuget.dgspec.json +PrinterClient/AutoUpgrade/obj/AutoUpgrade.csproj.nuget.g.props +PrinterClient/AutoUpgrade/obj/AutoUpgrade.csproj.nuget.g.targets +PrinterClient/AutoUpgrade/obj/project.assets.json +PrinterClient/AutoUpgrade/obj/project.nuget.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/apphost +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/apphost.exe +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.AssemblyInfo.cs +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.AssemblyInfoInputs.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.assets.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.csproj.AssemblyReference.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.csproj.CoreCompileInputs.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.csproj.FileListAbsolute.txt +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.dll +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.GeneratedMSBuildEditorConfig.editorconfig +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.genruntimeconfig.cache +PrinterClient/AutoUpgrade/obj/Debug/netcoreapp3.1/AutoUpgrade.pdb +PrinterClient/PrinterClient/.vscode/launch.json +PrinterClient/PrinterClient/obj/PrinterClient.csproj.nuget.dgspec.json +PrinterClient/PrinterClient/obj/PrinterClient.csproj.nuget.g.props +PrinterClient/PrinterClient/obj/PrinterClient.csproj.nuget.g.targets +PrinterClient/PrinterClient/obj/project.assets.json +PrinterClient/PrinterClient/obj/project.nuget.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/apphost +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/apphost.exe +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.AssemblyInfo.cs +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.AssemblyInfoInputs.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.assets.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.csproj.AssemblyReference.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.csproj.BuildWithSkipAnalyzers +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.csproj.CopyComplete +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.csproj.CoreCompileInputs.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.csproj.FileListAbsolute.txt +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.dll +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.GeneratedMSBuildEditorConfig.editorconfig +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.genruntimeconfig.cache +PrinterClient/PrinterClient/obj/Debug/netcoreapp3.1/PrinterClient.pdb +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/CyStat.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/CyStat64.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Buffers.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Codecs.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Codecs.Protobuf.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Handlers.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Transport.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/DotNetty.Transport.Libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Google.Protobuf.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.DependencyInjection.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.Logging.Abstractions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.Logging.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.Options.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Extensions.Primitives.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Microsoft.Win32.SystemEvents.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/Newtonsoft.Json.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/printer.uuid.txt +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.deps.json +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.dll.config +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.exe +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.pdb +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.runtimeconfig.dev.json +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/PrinterClient.runtimeconfig.json +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/protobuf-net.Core.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/protobuf-net.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Configuration.ConfigurationManager.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Diagnostics.DiagnosticSource.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Security.AccessControl.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Security.Cryptography.ProtectedData.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Security.Permissions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/System.Windows.Extensions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-arm/native/libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-arm64/native/libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-armel/native/libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-x64/native/libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/osx/native/libuv.dylib +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/unix/lib/netcoreapp2.1/System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/unix/lib/netcoreapp3.1/System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp2.1/System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/Microsoft.Win32.SystemEvents.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/System.Windows.Extensions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netstandard2.0/System.Security.AccessControl.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-arm/native/libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-x64/native/libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-x86/native/libuv.dll +TestView/TestView/obj/Debug/.NETFramework,Version=v4.5.2.AssemblyAttributes.cs +TestView/TestView/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs +TestView/TestView/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs +TestView/TestView/obj/Debug/App.g.cs +TestView/TestView/obj/Debug/App.g.i.cs +TestView/TestView/obj/Debug/DesignTimeResolveAssemblyReferences.cache +TestView/TestView/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache +TestView/TestView/obj/Debug/GeneratedInternalTypeHelper.g.cs +TestView/TestView/obj/Debug/GeneratedInternalTypeHelper.g.i.cs +TestView/TestView/obj/Debug/Loading.baml +TestView/TestView/obj/Debug/Loading.g.cs +TestView/TestView/obj/Debug/Loading.g.i.cs +TestView/TestView/obj/Debug/MainWindow.baml +TestView/TestView/obj/Debug/MainWindow.g.cs +TestView/TestView/obj/Debug/MainWindow.g.i.cs +TestView/TestView/obj/Debug/TaskControl.g.i.cs +TestView/TestView/obj/Debug/TaskInfoWindow.baml +TestView/TestView/obj/Debug/TaskInfoWindow.g.cs +TestView/TestView/obj/Debug/TaskInfoWindow.g.i.cs +TestView/TestView/obj/Debug/TestView_MarkupCompile.cache +TestView/TestView/obj/Debug/TestView_MarkupCompile.i.cache +TestView/TestView/obj/Debug/TestView_MarkupCompile.lref +TestView/TestView/obj/Debug/TestView.csproj.AssemblyReference.cache +TestView/TestView/obj/Debug/TestView.csproj.CopyComplete +TestView/TestView/obj/Debug/TestView.csproj.CoreCompileInputs.cache +TestView/TestView/obj/Debug/TestView.csproj.FileListAbsolute.txt +TestView/TestView/obj/Debug/TestView.csproj.GenerateResource.cache +TestView/TestView/obj/Debug/TestView.csproj.SuggestedBindingRedirects.cache +TestView/TestView/obj/Debug/TestView.exe +TestView/TestView/obj/Debug/TestView.g.resources +TestView/TestView/obj/Debug/TestView.pdb +TestView/TestView/obj/Debug/TestView.Properties.Resources.resources +TestView/TestView/obj/Debug/TempPE/Properties.Resources.Designer.cs.dll +TestView/TestView/bin/Debug/Newtonsoft.Json.dll +TestView/TestView/bin/Debug/Newtonsoft.Json.xml +TestView/TestView/bin/Debug/TestView.exe +TestView/TestView/bin/Debug/TestView.exe.config +TestView/TestView/bin/Debug/TestView.pdb +TestView/TestView/obj/Debug/build.force +TestView/TestView/obj/Debug/TestView_MarkupCompile.i.lref +TestView/packages/Newtonsoft.Json.13.0.3/.signature.p7s +TestView/packages/Newtonsoft.Json.13.0.3/LICENSE.md +TestView/packages/Newtonsoft.Json.13.0.3/Newtonsoft.Json.13.0.3.nupkg +TestView/packages/Newtonsoft.Json.13.0.3/packageIcon.png +TestView/packages/Newtonsoft.Json.13.0.3/README.md +TestView/packages/Newtonsoft.Json.13.0.3/lib/net20/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/net20/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/net35/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/net35/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/net40/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/net40/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/net45/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/net45/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/net6.0/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/net6.0/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard1.0/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard1.0/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard1.3/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard1.3/Newtonsoft.Json.xml +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard2.0/Newtonsoft.Json.dll +TestView/packages/Newtonsoft.Json.13.0.3/lib/netstandard2.0/Newtonsoft.Json.xml +TestView/.vs/TestView/FileContentIndex/64c275c3-c896-471e-9b80-378ddd44f3c4.vsidx +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Buffers.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Codecs.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Codecs.Protobuf.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Handlers.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Transport.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._DotNetty.Transport.Libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Google.Protobuf.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.DependencyInjection.Abstractions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.DependencyInjection.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.Logging.Abstractions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.Logging.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.Options.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Extensions.Primitives.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Microsoft.Win32.SystemEvents.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._Newtonsoft.Json.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._protobuf-net.Core.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._protobuf-net.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Configuration.ConfigurationManager.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Diagnostics.DiagnosticSource.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Runtime.CompilerServices.Unsafe.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Security.AccessControl.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Security.Cryptography.ProtectedData.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Security.Permissions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/._System.Windows.Extensions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-arm/native/._libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-arm64/native/._libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-armel/native/._libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/linux-x64/native/._libuv.so +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/osx/native/._libuv.dylib +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/unix/lib/netcoreapp2.1/._System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/unix/lib/netcoreapp3.1/._System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp2.1/._System.Security.Principal.Windows.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/._Microsoft.Win32.SystemEvents.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/._System.Drawing.Common.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netcoreapp3.1/._System.Windows.Extensions.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netstandard2.0/._System.Security.AccessControl.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win/lib/netstandard2.0/._System.Security.Cryptography.ProtectedData.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-arm/native/._libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-x64/native/._libuv.dll +PrinterClient/PrinterClient/bin/Debug/netcoreapp3.1/runtimes/win-x86/native/._libuv.dll diff --git a/PrinterClient/AutoUpgrade/AutoUpgrade.csproj b/PrinterClient/AutoUpgrade/AutoUpgrade.csproj new file mode 100644 index 0000000..c2946bd --- /dev/null +++ b/PrinterClient/AutoUpgrade/AutoUpgrade.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + diff --git a/PrinterClient/AutoUpgrade/Program.cs b/PrinterClient/AutoUpgrade/Program.cs new file mode 100644 index 0000000..1dc8e8e --- /dev/null +++ b/PrinterClient/AutoUpgrade/Program.cs @@ -0,0 +1,93 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace AutoUpgrade +{ + class Program + { + static bool ExecuteCommand(string fileName, string arguments) + { + /* 创建一个ProcessStartInfo对象 使用系统shell 指定命令和参数 设置标准输出 */ + var startInfo = new ProcessStartInfo(fileName, arguments) + { + RedirectStandardOutput = true + }; + + /* 启动 */ + var process = Process.Start(startInfo); + if (process != null) + { + /* 开始读取 */ + using (var streamReader = process.StandardOutput) + { + while (!streamReader.EndOfStream) + Console.WriteLine(streamReader.ReadLine()); + + if (!process.HasExited) + { + process.Kill(); + } + } + + return true; + } + + return false; + } + + static void DebugWriteLine(string output, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}, upgrade application: {output}"); + Console.ResetColor(); + } + + static void Main(string[] args) + { + /* 程序目录 */ + var filepath = "/root/netcoreapp3.1/"; + /* 下载名称 */ + var upgrade_file = Path.Combine(filepath, "AutoUpgrade", $"{Guid.NewGuid()}.zip"); + try + { + DebugWriteLine("downloading", ConsoleColor.Green); + + DebugWriteLine(args[0], ConsoleColor.Green); + + Console.ForegroundColor = ConsoleColor.DarkCyan; + + if (ExecuteCommand("wget", $"-O {upgrade_file} {args[0]}")) + { + DebugWriteLine("download complete", ConsoleColor.Green); + + DebugWriteLine("start upgrade", ConsoleColor.Green); + + //DebugWriteLine("stop printerclient.service", ConsoleColor.Green); + + //ExecuteCommand("systemctl", "stop printerclient.service"); + + DebugWriteLine($"unzip file, {upgrade_file} => {filepath}", ConsoleColor.Green); + + ExecuteCommand("unzip", $"-o {upgrade_file} -d {filepath}"); + + DebugWriteLine("start printerclient.service", ConsoleColor.Green); + + ExecuteCommand("systemctl", "restart printerclient.service"); + + DebugWriteLine("upgrade complete", ConsoleColor.Green); + } + else + { + DebugWriteLine("download error", ConsoleColor.Red); + } + } + catch (Exception ex) + { + DebugWriteLine($"error={ex.Message}", ConsoleColor.Red); + } + finally { ExecuteCommand("rm", upgrade_file); } + } + } +} + diff --git a/PrinterClient/PrinterClient.sln b/PrinterClient/PrinterClient.sln new file mode 100644 index 0000000..9050f98 --- /dev/null +++ b/PrinterClient/PrinterClient.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33424.131 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrinterClient", "PrinterClient\PrinterClient.csproj", "{3C8E7DD6-A14C-4613-AE71-D445742EE112}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoUpgrade", "AutoUpgrade\AutoUpgrade.csproj", "{EC3F20F1-ABB8-432A-9546-289C37B6A1AF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3C8E7DD6-A14C-4613-AE71-D445742EE112}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C8E7DD6-A14C-4613-AE71-D445742EE112}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C8E7DD6-A14C-4613-AE71-D445742EE112}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C8E7DD6-A14C-4613-AE71-D445742EE112}.Release|Any CPU.Build.0 = Release|Any CPU + {EC3F20F1-ABB8-432A-9546-289C37B6A1AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC3F20F1-ABB8-432A-9546-289C37B6A1AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC3F20F1-ABB8-432A-9546-289C37B6A1AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC3F20F1-ABB8-432A-9546-289C37B6A1AF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DE4EAAEE-7F2C-42EF-95FF-CECF8FF0608F} + EndGlobalSection +EndGlobal diff --git a/PrinterClient/PrinterClient/BoxServer.cs b/PrinterClient/PrinterClient/BoxServer.cs new file mode 100644 index 0000000..5c91bae --- /dev/null +++ b/PrinterClient/PrinterClient/BoxServer.cs @@ -0,0 +1,620 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using DotNetty.Buffers; +using DotNetty.Handlers.Timeout; +using DotNetty.Transport.Bootstrapping; +using DotNetty.Transport.Channels; +using DotNetty.Transport.Channels.Sockets; +using Google.Protobuf.WellKnownTypes; + +namespace PrinterClient; + +public class BoxServer +{ + long serialNo = 0; + + string equipNo = "TWS-TR-01"; + + Bootstrap bootstrap = new(); + + MultithreadEventLoopGroup group = new(); + + static IChannel clientChannel; + + ///* 是否有打印任务正在进行 */ + //bool isPrinter = false; + ///* 当前正在打印的订单号 */ + //string TerminalPrintTaskState_PrintOrderCode = ""; + ///* 当前订单执行状态 */ + //int TerminalPrintTaskState_Status = 0; + + public static int Total = 0; + + public static bool Status = false; + + public BoxServer(string equipNo) + { + this.equipNo = equipNo; + } + + public void Connect(string address, int port) + { + bootstrap + .Group(group) + .Channel() + .Option(ChannelOption.TcpNodelay, true) + .Option(ChannelOption.ConnectTimeout, TimeSpan.FromSeconds(3)) + .Option(ChannelOption.RcvbufAllocator, new FixedRecvByteBufAllocator(1024)) + .Handler(new ActionChannelInitializer(channel => + { + var pipeline = channel.Pipeline; + pipeline.AddLast(new IdleStateHandler(60, 60, 60)); + pipeline.AddLast(new ClientHandler(ReceiveHandler, Connect)); + })); + + bootstrap.RemoteAddress(new IPEndPoint(IPAddress.Parse(address), port)); + + Connect(); + + new Task(WorkThread, TaskCreationOptions.LongRunning).Start(); + } + + private async void Connect() + { + try + { + Interlocked.Increment(ref Total); + if (Total == 1) + { + if (clientChannel == null) + { + Program.DebugWriteLine("try conneting"); + + clientChannel = await bootstrap.ConnectAsync(); + } + } + } + catch (Exception ex) + { + Total = 0; + + LogUtils.AppendError(ex); + + Thread.Sleep(10000); + + Connect(); + } + } + + private async void SendHandler(PrintMessage printMessage) + { + await Task.Run(() => + { + try + { + if (clientChannel == null) + return; + + var message = Unpooled.Buffer(); + message.WriteBytes(printMessage.Serialize()); + clientChannel.WriteAndFlushAsync(message); + + Program.DebugWriteLine($"common send: serialNo={printMessage.serialNo}"); + } + catch (Exception ex) { LogUtils.AppendError(ex); } + }); + } + + private async void ReceiveHandler(PrintMessage printMessage) + { + await Task.Run(() => + { + switch (printMessage.ecsType) + { + /* 通用回复指令 */ + case TaskType.CommonResponse: + Program.DebugWriteLine($"common response: serialNo={printMessage.serialNo}, status={printMessage.commandResponse.Status}, remark={printMessage.commandResponse.Remark}"); + break; + + /* 下发打印任务 */ + case TaskType.TerminalPrinttask: + TerminalPrintTaskHandle(printMessage.serialNo, printMessage.terminalPrintTask); + break; + + /* 程序版本回复 */ + case TaskType.TerminalCheckversionResult: + TerminalCheckVersionResultHandle(printMessage.terminalCheckVersionResult); + break; + + /* 终端控制指令 */ + case TaskType.TerminalControl: + TerminalControlHandle(printMessage.terminalControl); + break; + } + }); + } + + private void WorkThread() + { + while (true) + { + if (TimerUtils.IsInterval("TerminalStateUpdateHandle", 1000 * 10)) + TerminalStateUpdateHandle(); + + if (TimerUtils.IsInterval("TerminalCheckVersionHandle", 1000 * 60 * 10)) + TerminalCheckVersionHandle(); + + ///* 打印盒子在获取打印任务后开始执行打印任务,打印盒子定时上传打印状态(定时2秒上传一次) */ + //if (isPrinter) + //{ + // if (TimerUtils.IsInterval("TerminalPrintTaskStateHandle", 1000 * 2)) + // TerminalPrintTaskStateHandle(); + //} + + Thread.Sleep(100); + } + } + + /// + /// 通用回复指令 + /// + /// 消息序列号 + /// 状态, 0=成功,1=异常 + /// 描述情况 + private async void CommonResponseHandle(string serialNo, int status, string remark) + { + await Task.Run(() => + { + PrintMessage printMessage = new() + { + serialNo = serialNo, + ecsType = TaskType.CommonResponse, + commandResponse = new() + { + equipNo = equipNo, + equipCode = Program.Uuid, + Status = status.ToString(), + Remark = remark, + } + }; + + SendHandler(printMessage); + }); + } + + /// + /// 上传终端状态数据 + /// + private async void TerminalStateUpdateHandle() + { + await Task.Run(() => + { + PrintMessage printMessage = new() + { + serialNo = (serialNo++).ToString(), + ecsType = TaskType.TerminalStateUpdate, + terminalStateUpdate = new() + { + equipNo = equipNo, + equipType = "3", + equipCode = Program.Uuid, + Longitude = "", + Latitude = "", + equipVer = ReadMe.Version, + equipTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), + Ip = "", + equipStatus = Printer.BoxStatus.ToString(), + printerStatus = Printer.Status.ToString(), + peripheralFeatureIds = "110001", + printerCode = Printer.Serial + } + }; + + SendHandler(printMessage); + }); + } + + /* + 5,打印4张时,百分之80几率只能打印成功2张后平台状态一直停留在打印中或盒子开始处理等状态。 + */ + + /// + /// 下发打印任务 + /// + /// + /// + private async void TerminalPrintTaskHandle(string serialNo, TerminalPrintTask result) + { + await Task.Run(() => + { + if (result.equipCode.Equals(Program.Uuid)) + { + var printerStatus = Printer.Status; + + /* 生成唯一ID */ + var uuid = Guid.NewGuid().ToString(); + + /* 盒子收到指令 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 12, printerStatus); + + Program.DebugWriteLine($"{result.printOrderCode}, checking Printer status = {printerStatus}"); + + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "收到指令"); + + if (printerStatus == (int)PrinterStatus.DriveFailed || + printerStatus == (int)PrinterStatus.NotDriven || + printerStatus == (int)PrinterStatus.Maintenance || + printerStatus == (int)PrinterStatus.NoPaper || + printerStatus == (int)PrinterStatus.Sleep) + { + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "打印失败(打印机异常)"); + + Program.DebugWriteLine("打印机异常"); + + /* 异常 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 15, printerStatus); + + return; + } + else if (printerStatus == (int)PrinterStatus.Printing) + { + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "打印失败(正在打印中)"); + + Program.DebugWriteLine("打印机正在打印中"); + + /* 盒子当前有任务执行 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 16, printerStatus); + + return; + } + + /* 开始执行打印任务 */ + Program.DebugWriteLine("开始执行打印任务"); + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "开始执行打印任务"); + + Directory.CreateDirectory(Program.ImagePath); + string error = ""; + string filename = $"{Program.ImagePath}{result.printOrderCode}.jpg"; + try + { + Program.DebugWriteLine($"Current task order number: {result.printOrderCode}"); + + Printer.BoxStatus = (int)BoxStatus.Download; + + /* 盒子开始处理 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 13, Printer.Status); + Thread.Sleep(2000); + /* 开始下载文件 */ + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "开始下载文件"); + Program.DebugWriteLine($"开始下载文件 {result.printFileUrl} {filename}"); + TaskDispatcher.ExecuteCommand("wget", $" --read-timeout=5 --tries=5 {result.printFileUrl} -O {filename}", out string output); + Program.DebugWriteLine($"下载完成, {output}"); + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "下载完成"); + DebugTool.UploadTaskImage(uuid, filename); + /* 下载完成 */ + Printer.BoxStatus = (int)BoxStatus.Normal; + /* 盒子开始打印 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 14, Printer.Status); + + Printer.Printing = true; + + Program.DebugWriteLine("开始打印"); + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "开始打印"); + while (!Printer.Print(result.fileFormatId, result.printModeId, result.printSizeId, filename, out string job)) + { + Program.DebugWriteLine("打印失败,5s后重试"); + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "打印失败,5s后重试"); + Thread.Sleep(5000); + } + + /* 等待盒子打印完成 */ + DateTime current = DateTime.Now; + while (true) + { + TerminalPrintTaskStateHandle(result.printOrderCode, 14, Printer.Status); + + /* 最大等待时长1分钟 */ + if (DateTime.Now - current >= TimeSpan.FromMinutes(1)) + { + error = "打印超时"; + + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "打印超时"); + + while (Printer.QueryEntries() != null) + { + Program.DebugWriteLine($"删除所有的打印任务"); + + Printer.Clear(); + + Thread.Sleep(1000); + } + + break; + } + + if (Printer.Status != (int)PrinterStatus.Printing) + break; + + Thread.Sleep(2000); + } + + Thread.Sleep(2000); + + /* 打印超时 */ + if (error == "打印超时") + TerminalPrintTaskStateHandle(result.printOrderCode, 23, Printer.Status); + else /* 打印成功 */ + { + Thread.Sleep(5000); + TerminalPrintTaskStateHandle(result.printOrderCode, 21, Printer.Status); + } + } + catch (Exception ex) + { + LogUtils.AppendError(ex); + + /* 异常 */ + TerminalPrintTaskStateHandle(result.printOrderCode, 15, Printer.Status); + } + finally + { + /* 打印完成 */ + Program.DebugWriteLine($"打印任务结束 {error}"); + DebugTool.UploadTaskStatus(uuid, result.printOrderCode, "打印任务结束"); + + Printer.Printing = false; + + if (!Program.ImageSave) + { + if (File.Exists(filename)) + File.Delete(filename); + } + } + } + }); + } + + ///// + ///// 上传打印任务情况 + ///// + //private async void TerminalPrintTaskStateHandle() + //{ + // await Task.Run(() => + // { + // PrintMessage printMessage = new() + // { + // serialNo = (serialNo++).ToString(), + // ecsType = TaskType.TerminalPrinttaskState, + // terminalPrintTaskState = new() + // { + // equipNo = equipNo, + // equipCode = Program.Uuid, + // printOrderCode = TerminalPrintTaskState_PrintOrderCode, + // Status = TerminalPrintTaskState_Status.ToString(), + // printerStatus = Printer.Status.ToString() + // } + // }; + + // SendHandler(printMessage); + // }); + //} + + /// + /// 上传打印任务情况 + /// + private async void TerminalPrintTaskStateHandle(string printOrderCode, int status, int printerStatus) + { + await Task.Run(() => + { + PrintMessage printMessage = new() + { + serialNo = (serialNo++).ToString(), + ecsType = TaskType.TerminalPrinttaskState, + terminalPrintTaskState = new() + { + equipNo = equipNo, + equipCode = Program.Uuid, + printOrderCode = printOrderCode, + Status = status.ToString(), + printerStatus = printerStatus.ToString() + } + }; + + SendHandler(printMessage); + }); + } + + ///// + ///// 终端接收任务回复 + ///// 订单号 + ///// 状态 + ///// + //private async void TerminalPrintTaskResultHandle(string printOrderCode, int status, string remark = "") + //{ + // await Task.Run(() => + // { + // PrintMessage printMessage = new() + // { + // serialNo = (serialNo++).ToString(), + // ecsType = TaskType.TERMINAL_PRINTTASK_RESULT, + // terminalPrintTaskResult = new() + // { + // equipNo = equipNo, + // equipCode = uuid, + // printOrderCode = printOrderCode, + // status = status.ToString(), + // remark = remark, + // } + // }; + + // SendHandler(printMessage); + // }); + //} + + /// + /// 终端查询版本 + /// + private async void TerminalCheckVersionHandle() + { + await Task.Run(() => + { + PrintMessage printMessage = new() + { + serialNo = (serialNo++).ToString(), + ecsType = TaskType.TerminalCheckversion, + terminalCheckVersion = new() + { + equipCode = Program.Uuid, + Type = "1", + versionCode = ReadMe.Version, + } + }; + + SendHandler(printMessage); + }); + } + + /// + /// 程序版本回复 + /// + /// + private async void TerminalCheckVersionResultHandle(TerminalCheckVersionResult result) + { + await Task.Run(() => + { + if (string.IsNullOrEmpty(result.versionCode)) + return; + + Program.DebugWriteLine($"remote version {result.versionCode}, url {result.verUrl}"); + + if (!string.IsNullOrEmpty(result.versionCode) && result.versionCode != ReadMe.Version) + { + TaskDispatcher.ExecuteCommand("dotnet", $"AutoUpgrade/AutoUpgrade.dll {result.verUrl}", out string _); + } + }); + } + + /// + /// 终端控制 + /// + /// + private async void TerminalControlHandle(TerminalControl control) + { + await Task.Run(() => + { + int status = 21; /* 失败 */ + + switch (control.Type) + { + /* 重启应用 */ + case "1101": + Program.DebugWriteLine("接收到 重启应用 指令"); + TerminalControlUpdateHandle(control.orderCode, control.Type, status); + Thread.Sleep(5000); + TaskDispatcher.AsyncExecuteCommand("systemctl", "restart printerclient.service"); + break; + + /* 重启系统 */ + case "1201": + Program.DebugWriteLine("接收到 重启系统 指令"); + TerminalControlUpdateHandle(control.orderCode, control.Type, status); + Thread.Sleep(5000); + TaskDispatcher.AsyncExecuteCommand("reboot", ""); + break; + } + }); + } + + /// + /// 终端控制回复 + /// + /// + private async void TerminalControlUpdateHandle(string orderCode, string type, int status) + { + await Task.Run(() => + { + PrintMessage printMessage = new() + { + serialNo = (serialNo++).ToString(), + ecsType = TaskType.TerminalControlUpdate, + terminalControlUpdate = new() + { + equipNo = equipNo, + equipCode = Program.Uuid, + orderCode = orderCode, + Type = type, + Status = status.ToString() + } + }; + + SendHandler(printMessage); + }); + } + + public class ClientHandler : ChannelHandlerAdapter + { + private readonly IByteBuffer initialMessage = null; + + private readonly Action DroplineAction = null; + + private readonly Action Receiveaction = null; + + public ClientHandler(Action receiveaction, Action droplineAction) + { + this.Receiveaction = receiveaction; + this.DroplineAction = droplineAction; + } + + public override void ChannelActive(IChannelHandlerContext context) + { + BoxServer.Status = true; + + Program.DebugWriteLine("connect success"); + context.WriteAndFlushAsync(initialMessage); + } + + public override void ChannelRead(IChannelHandlerContext context, object message) + { + if (message is IByteBuffer byteBuffer) + { + Receiveaction.Invoke(byteBuffer.Array.Deserialize(byteBuffer.ArrayOffset + byteBuffer.ReaderIndex, byteBuffer.ReadableBytes)); + } + } + + public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush(); + + public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) + { + Program.DebugWriteLine("Exception: " + exception); + context.CloseAsync(); + } + + public override void HandlerAdded(IChannelHandlerContext context) + { + base.HandlerAdded(context); + } + + public override void HandlerRemoved(IChannelHandlerContext context) + { + BoxServer.Status = false; + + Program.DebugWriteLine($"receive {context.Channel.LocalAddress} disconnect notification. current connect {clientChannel.LocalAddress}"); + + if (context.Channel.LocalAddress.ToString().Equals(clientChannel.LocalAddress.ToString())) + { + Total = 0; + + clientChannel = null; + + DroplineAction(); + } + + base.HandlerRemoved(context); + } + } +} + diff --git a/PrinterClient/PrinterClient/DebugTool.cs b/PrinterClient/PrinterClient/DebugTool.cs new file mode 100644 index 0000000..24a59a0 --- /dev/null +++ b/PrinterClient/PrinterClient/DebugTool.cs @@ -0,0 +1,135 @@ +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Net; +using System.Net.Sockets; +using System.IO; + +namespace PrinterClient +{ + public class TcpBuffer + { + public TcpClient Client; + + public byte[] Buffer = new byte[1024 * 1024]; + } + + public class DebugTool + { + class Model + { + public int Type { get; set; } + + public object MsgInfo { get; set; } + + public override string ToString() => Newtonsoft.Json.JsonConvert.SerializeObject(this); + + public Model(int Type, object MsgInfo = null) { this.Type = Type; this.MsgInfo = MsgInfo; } + } + + private static TcpClient tcpClient = null; + + private static TcpListener tcpListener = null; + + public static void Start() + { + tcpListener = new TcpListener(IPAddress.Any, 8566); + tcpListener.Start(); + + tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null); + + /* 每2秒上传一次状态信息 */ + Task.Run(() => + { + while (true) + { + Write(new Model(0, new + { + UUID = Program.Uuid, + Serial = Printer.Serial, + ServiceStatus = BoxServer.Status, + PrinterStatus = Printer.Status, + })); + + Thread.Sleep(2000); + } + }); + } + + public static void Write(object message) + { + try + { + if (tcpClient?.Connected == true) + { + var buffer = Encoding.UTF8.GetBytes(message.ToString() + "\n"); + + tcpClient.GetStream().Write(buffer, 0, buffer.Length); + } + } + catch { } + } + + public static void UploadTaskStatus(string uuid, string id, string status) + { + Write(new Model(1, new + { + Uuid = uuid, + ID = id, + Status = status, + })); + } + + public static void UploadTaskImage(string uuid, string filename) + { + Write(new Model(2, new + { + Uuid = uuid, + Base64String = Convert.ToBase64String(File.ReadAllBytes(filename)) + })); + } + + private static void BeginRead(TcpClient client) + { + tcpClient = client; + + var tb = new TcpBuffer() { Client = tcpClient }; + + tcpClient.GetStream().BeginRead(tb.Buffer, 0, tb.Buffer.Length, ReadCallback, tb); + } + + private static void AcceptTcpClientCallback(IAsyncResult ar) + { + try + { + if (tcpClient != null) + { + tcpClient.Close(); + tcpClient = null; + } + + BeginRead(tcpListener.EndAcceptTcpClient(ar)); + } + catch { } + + tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null); + } + + private static void ReadCallback(IAsyncResult ar) + { + try + { + var tb = ar.AsyncState as TcpBuffer; + + var length = tb.Client.GetStream().EndRead(ar); + + Console.WriteLine(Encoding.ASCII.GetString(tb.Buffer, 0, length)); + + BeginRead(tcpListener.EndAcceptTcpClient(ar)); + } + catch { } + } + } +} + diff --git a/PrinterClient/PrinterClient/PrinterClient.csproj b/PrinterClient/PrinterClient/PrinterClient.csproj new file mode 100644 index 0000000..a2fefe0 --- /dev/null +++ b/PrinterClient/PrinterClient/PrinterClient.csproj @@ -0,0 +1,56 @@ + + + + Exe + netcoreapp3.1 + + + + latest + + + latest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PrinterClient/PrinterClient/Program.cs b/PrinterClient/PrinterClient/Program.cs new file mode 100644 index 0000000..6d56203 --- /dev/null +++ b/PrinterClient/PrinterClient/Program.cs @@ -0,0 +1,72 @@ +using System; +using System.Configuration; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +namespace PrinterClient; + +class Program +{ + readonly static string UuidPath = "printer.uuid.txt"; + + static BoxServer boxServer; + + static bool debugging = false; + + public static string ImagePath = "Image/"; + + public static bool ImageSave = false; + + public static string Platform = ""; + + public static string Uuid = Guid.NewGuid().ToString(); + + static void Main(string[] args) + { + DebugTool.Start(); + + /* 获取运行平台类型 */ + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + Platform = "Linux"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + Platform = "OSX"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + Platform = "Windows"; + + /* 生成唯一编码 */ + if (File.Exists(UuidPath)) + { + Uuid = File.ReadAllText(UuidPath); + } + else + { + File.WriteAllText(UuidPath, Uuid); + } + + var address = ConfigurationManager.AppSettings["address"].ToString(); + var port = Convert.ToInt32(ConfigurationManager.AppSettings["port"]); + + debugging = Convert.ToBoolean(ConfigurationManager.AppSettings["debugging"]); + ImageSave = Convert.ToBoolean(ConfigurationManager.AppSettings["image_save"]); + + DebugWriteLine($"uuid: {Uuid}, version: {ReadMe.Version}"); + + DebugWriteLine($"remote address: {address}, port: {port}, debugging: {debugging}, image_save: {ImageSave}"); + + boxServer = new BoxServer("TWS-TR-01"); + + boxServer.Connect(address, port); + + while (true) { Thread.Sleep(1000); } + } + + public static void DebugWriteLine(string value) + { + var str = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: {value}"; + + if (debugging) + LogUtils.AppendLog(str); + else + Console.WriteLine(str); + } +} \ No newline at end of file diff --git a/PrinterClient/PrinterClient/RX1/CyStatus.cs b/PrinterClient/PrinterClient/RX1/CyStatus.cs new file mode 100644 index 0000000..72a2894 --- /dev/null +++ b/PrinterClient/PrinterClient/RX1/CyStatus.cs @@ -0,0 +1,317 @@ +using System; +using System.Drawing.Printing; +using System.IO; +using System.Runtime.InteropServices; + +namespace PrinterClient +{ + public class CyStatus + { + public const int GROUP_USUALLY = 0x10000; + public const int GROUP_SETTING = 0x20000; + public const int GROUP_HARDWARE = 0x40000; + public const int GROUP_SYSTEM = 0x80000; + public const int GROUP_FLSHPROG = 0x100000; + public const int STATUS_ERROR = int.MinValue; + public const int STATUS_USUALLY_IDLE = 0x10001; + public const int STATUS_USUALLY_PRINTING = 0x10002; + public const int STATUS_USUALLY_STANDSTILL = 0x10004; + public const int STATUS_USUALLY_PAPER_END = 0x10008; + public const int STATUS_USUALLY_RIBBON_END = 0x10010; + public const int STATUS_USUALLY_COOLING = 0x10020; + public const int STATUS_USUALLY_MOTCOOLING = 0x10020; + public const int STATUS_SETTING_COVER_OPEN = 0x20001; + public const int STATUS_SETTING_PAPER_JAM = 0x20002; + public const int STATUS_SETTING_RIBBON_ERR = 0x20004; + public const int STATUS_SETTING_PAPER_ERR = 0x20008; + public const int STATUS_SETTING_DATA_ERR = 0x20010; + public const int STATUS_SETTING_SCRAPBOX_ERR = 0x20020; + public const int STATUS_HARDWARE_ERR01 = 0x40001; + public const int STATUS_HARDWARE_ERR02 = 0x40002; + public const int STATUS_HARDWARE_ERR03 = 0x40004; + public const int STATUS_HARDWARE_ERR04 = 0x40008; + public const int STATUS_HARDWARE_ERR05 = 0x40010; + public const int STATUS_HARDWARE_ERR06 = 0x40020; + public const int STATUS_HARDWARE_ERR07 = 0x40040; + public const int STATUS_HARDWARE_ERR08 = 0x40080; + public const int STATUS_HARDWARE_ERR09 = 0x40100; + public const int STATUS_HARDWARE_ERR10 = 0x40200; + public const int STATUS_SYSTEM_ERR01 = 0x80001; + public const int STATUS_FLSHPROG_IDLE = 0x100001; + public const int STATUS_FLSHPROG_WRITING = 0x100002; + public const int STATUS_FLSHPROG_FINISHED = 0x100004; + public const int STATUS_FLSHPROG_DATA_ERR1 = 0x100008; + public const int STATUS_FLSHPROG_DEVICE_ERR1 = 0x100010; + public const int STATUS_FLSHPROG_OTHERS_ERR1 = 0x100020; + public const int CVG_USUALLY = 0x10000; + public const int CVG_SETTING = 0x20000; + public const int CVG_HARDWARE = 0x40000; + public const int CVG_SYSTEM = 0x80000; + public const int CVG_FLSHPROG = 0x100000; + public const int CVSTATUS_ERROR = int.MinValue; + public const int CVS_USUALLY_IDLE = 0x10001; + public const int CVS_USUALLY_PRINTING = 0x10002; + public const int CVS_USUALLY_STANDSTILL = 0x10004; + public const int CVS_USUALLY_PAPER_END = 0x10008; + public const int CVS_USUALLY_RIBBON_END = 0x10010; + public const int CVS_USUALLY_COOLING = 0x10020; + public const int CVS_USUALLY_MOTCOOLING = 0x10040; + public const int CVS_SETTING_COVER_OPEN = 0x20001; + public const int CVS_SETTING_PAPER_JAM = 0x20002; + public const int CVS_SETTING_RIBBON_ERR = 0x20004; + public const int CVS_SETTING_PAPER_ERR = 0x20008; + public const int CVS_SETTING_DATA_ERR = 0x20010; + public const int CVS_SETTING_SCRAP_ERR = 0x20020; + public const int CVS_HARDWARE_ERR01 = 0x40001; + public const int CVS_HARDWARE_ERR02 = 0x40002; + public const int CVS_HARDWARE_ERR03 = 0x40004; + public const int CVS_HARDWARE_ERR04 = 0x40008; + public const int CVS_HARDWARE_ERR05 = 0x40010; + public const int CVS_HARDWARE_ERR06 = 0x40020; + public const int CVS_HARDWARE_ERR07 = 0x40040; + public const int CVS_HARDWARE_ERR08 = 0x40080; + public const int CVS_HARDWARE_ERR09 = 0x40100; + public const int CVS_HARDWARE_ERR10 = 0x40200; + public const int CVS_SYSTEM_ERR01 = 0x80001; + public const int CVS_FLSHPROG_IDLE = 0x100001; + public const int CVS_FLSHPROG_WRITING = 0x100002; + public const int CVS_FLSHPROG_FINISHED = 0x100004; + public const int CVS_FLSHPROG_DATA_ERR1 = 0x100008; + public const int CVS_FLSHPROG_DEVICE_ERR1 = 0x100010; + public const int CVS_FLSHPROG_OTHERS_ERR1 = 0x100020; + public const short CUTTER_MODE_STANDARD = 0; + public const short CUTTER_MODE_NONSCRAP = 1; + public const short CUTTER_MODE_2INCHCUT = 120; + + public const string path = "CyStat64.dll"; + +#pragma warning disable CS0618 // 类型或成员已过时 + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvInitialize([MarshalAs(UnmanagedType.LPWStr)] string pszPortName); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetVersion(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetSensorInfo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetMedia(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetStatus(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetPQTY(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetCounterL(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetCounterA(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetCounterB(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetMediaCounter(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetMediaColorOffset(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetMediaLotNo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "CvSetColorDataVersion", ExactSpelling = true, SetLastError = true)] + public static extern int CvSetColorDataVersion_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetColorDataWrite", ExactSpelling = true, SetLastError = true)] + public static extern int CvSetColorDataWrite_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetColorDataVersion(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvSetColorDataClear(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetColorDataChecksum(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetSerialNo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetResolutionH(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetResolutionV(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvGetFreeBuffer(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvSetClearCounterA(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvSetClearCounterB(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int CvSetFirmwUpdateMode(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetFirmwDataWrite", ExactSpelling = true, SetLastError = true)] + public static extern int CvSetFirmwDataWrite_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "CvSetCommand", ExactSpelling = true, SetLastError = true)] + public static extern int CvSetCommand_(int lPortNum, long lpCmd, int dwCmdLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "CvGetCommand", ExactSpelling = true, SetLastError = true)] + public static extern int CvGetCommand_(int lPortNum, long lpCmd, int dwCmdLen, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpRetBuff, int dwRetBuffSize, ref long lpdwRetLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "CvGetCommandEX", ExactSpelling = true, SetLastError = true)] + public static extern int CvGetCommandEX_(int lPortNum, long lpCmd, int dwCmdLen, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpRetBuff, int dwRetBuffSize); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int PortInitialize([MarshalAs(UnmanagedType.LPWStr)] string pszPortName); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetFirmwVersion(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetSensorInfo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMedia(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetStatus(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetPQTY(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterL(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterA(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterB(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterP(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterMatte(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetCounterM(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMediaCounter(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMediaCounter_R(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMediaColorOffset(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMediaLotNo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetMediaIdSetInfo(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetColorDataVersion", ExactSpelling = true, SetLastError = true)] + public static extern int SetColorDataVersion_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetColorDataWrite", ExactSpelling = true, SetLastError = true)] + public static extern int SetColorDataWrite_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetColorDataVersion(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetColorDataClear(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetColorDataChecksum(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetSerialNo(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetResolutionH(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetResolutionV(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetFreeBuffer(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetClearCounterA(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetClearCounterB(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetClearCounterM(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetCounterP(int lPortNum, int Counter); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetFirmwUpdateMode(int lPortNum); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetFirmwDataWrite", ExactSpelling = true, SetLastError = true)] + public static extern int SetFirmwDataWrite_(int lPortNum, long lpBuff, int bLen); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int SetCutterMode(int lPortNum, int d); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "SetCommand", ExactSpelling = true, SetLastError = true)] + public static extern int SetCommand_(int lPortNum, long lpCmd, int dwCmdLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "GetCommand", ExactSpelling = true, SetLastError = true)] + public static extern int GetCommand_(int lPortNum, long lpCmd, int dwCmdLen, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpRetBuff, int dwRetBuffSize, ref long lpdwRetLen); + + [DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "GetCommandEX", ExactSpelling = true, SetLastError = true)] + public static extern int GetCommandEX_(int lPortNum, long lpCmd, int dwCmdLen, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpRetBuff, int dwRetBuffSize); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetRfidMediaClass(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetRfidReserveData(int lPortNum, [MarshalAs(UnmanagedType.VBByRefStr)] ref string s, int dwPage); + + [DllImport(path, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern int GetInitialMediaCount(int lPortNum); +#pragma warning restore CS0618 // 类型或成员已过时 + + public static void SendFileToPrinter(string printname, string szFileName) + { + PrintDocument pd = new PrintDocument(); + pd.DocumentName = szFileName; + pd.PrintPage += PicturePrintDocument_PrintPage; //注册打印事件 + pd.Print(); + } + + private static void PicturePrintDocument_PrintPage(object sender, PrintPageEventArgs e) + { + var pd = (PrintDocument)sender; + //打开文件 + FileStream fs = File.OpenRead(pd.DocumentName); + //转换为BYTE + int filelength = (int)fs.Length; + byte[] imageByte = new byte[filelength]; //建立一个字节数组 + fs.Read(imageByte, 0, filelength); //按字节流读取 + //转换为 IMAGE + System.Drawing.Image image = System.Drawing.Image.FromStream(fs); + fs.Close(); + + e.Graphics.DrawImage(image, 0, 0); //img大小 + //e.Graphics.DrawString(TicCode, DrawFont, brush, 600, 600); //绘制字符串 + e.HasMorePages = false; + } + } +} \ No newline at end of file diff --git a/PrinterClient/PrinterClient/ReadMe.cs b/PrinterClient/PrinterClient/ReadMe.cs new file mode 100644 index 0000000..34c983c --- /dev/null +++ b/PrinterClient/PrinterClient/ReadMe.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace PrinterClient; + +/// +/// 版本信息 +/// +static class ReadMe +{ + public static string AppName { get => "PrinterClient"; } + + public static string Version => Versions.First().Key; + + static readonly Dictionary> Versions = new() + { + ["1.1.0 Alpha Bulid 20231018"] = new List() + { + "删除: 检测打印机更换功能", + "删除: 打印机驱动加载功能", + "删除: 打印机参数设置功能", + "修改: 发送给调试软件日志时延时1s变为不延时", + "修改: 打印成功后, 延时5s上传状态", + "添加: 驱动加载、打印、参数设置由脚本完成", + }, + ["1.0.9 Alpha Bulid 20230913"] = new List() + { + "修改若干BUG", + }, + ["1.0.8 Alpha Bulid 20230829"] = new List() + { + "修改若干BUG", + }, + ["1.0.7 Alpha Bulid 20230207"] = new List() + { + "添加重启系统及应用指令", + }, + ["1.0.6 Alpha Bulid 20230109"] = new List() + { + "添加打印机序列号获取及上传", + "启动时主动添加一次打印机驱动", + }, + ["1.0.5 Alpha Bulid 20221220"] = new List() + { + "添加打印超时的状态上传" + }, + ["1.0.4 Alpha Bulid 20221027"] = new List() + { + "打印任务超时后, 进行任务清空的操作", + "检测不到默认打印机时,重新设置默认打印机", + "添加打印失败后重新尝试打印的操作", + "打印超时问题未解决" + }, + ["1.0.3 Alpha Bulid 20220307"] = new List() + { + "添加: 设置打印机打印格式、类型、尺寸", + }, + ["1.0.2 Alpha Bulid 20211208"] = new List() + { + "修复: 没有正确识别打印机休眠状态", + "修复: 重连导致服务器过多连接", + "添加: 打印机禁用状态下, 发送激活命令启用打印机", + }, + ["1.0.1 Alpha Bulid 20211105"] = new List() + { + "实现升级功能", + "添加设置信息", + }, + ["1.0.0 Alpha Bulid 20211103"] = new List() + { + "实现基本功能", + }, + }; + + public static void Bulid() + { + var path = Path.GetDirectoryName(typeof(Program).Module.FullyQualifiedName); + using FileStream fr = new(Path.Combine(path, "ReadMe.md"), FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); + using StreamWriter sw = new(fr, Encoding.UTF8); + StringBuilder sb = new(); + sb.AppendLine($"# {AppName} 版本历史介绍").AppendLine(); + foreach (var item in Versions) + { + sb.AppendLine($"## {item.Key}"); + foreach (var value in item.Value) + sb.AppendLine($"* {value}"); + sb.AppendLine(); + } + sb.Remove(sb.Length - 2, 2); + sw.Write(sb); + } + +} + diff --git a/PrinterClient/PrinterClient/TaskDispatcher.cs b/PrinterClient/PrinterClient/TaskDispatcher.cs new file mode 100644 index 0000000..7fd34c6 --- /dev/null +++ b/PrinterClient/PrinterClient/TaskDispatcher.cs @@ -0,0 +1,485 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +namespace PrinterClient +{ + public enum BoxStatus : int + { + /// + /// 正常 + /// + Normal = 0, + + /// + /// 异常 + /// + Failed = 201, + + /// + /// 下载中 + /// + Download = 104, + + /// + /// 升级中 + /// + Upgrade = 301, + } + + public enum PrinterStatus : int + { + /// + /// 正常 + /// + Normal = 101, + + /// + /// 打印中 + /// + Printing = 102, + + /// + /// 等待文件下载 + /// + Waiting_For_File_Download = 104, + + /// + /// 检测中 + /// + Testing = 109, + + /// + /// 无纸 + /// + NoPaper = 201, + + /// + /// 休眠 + /// + Sleep = 302, + + /// + /// 未驱动 + /// + NotDriven = 306, + + /// + /// 驱动失败 + /// + DriveFailed = 310, + + /// + /// 维护 + /// + Maintenance = 209, + } + + public class TaskDispatcher + { + public static bool ExecuteCommand(string fileName, string arguments, out string output) + { + output = string.Empty; + + /* 创建一个ProcessStartInfo对象 使用系统shell 指定命令和参数 设置标准输出 */ + var startInfo = new ProcessStartInfo(fileName, arguments) + { + RedirectStandardOutput = true + }; + + /* 启动 */ + var process = Process.Start(startInfo); + if (process != null) + { + /* 开始读取 */ + using (var streamReader = process.StandardOutput) + { + while (!streamReader.EndOfStream) + { + output += streamReader.ReadLine() + "\r\n"; + } + + if (!process.HasExited) + { + process.Kill(); + } + } + + return true; + } + + return false; + } + + public static void AsyncExecuteCommand(string fileName, string arguments) + { + LogUtils.AppendLog(fileName + " " + arguments); + + /* 创建一个ProcessStartInfo对象 使用系统shell 指定命令和参数 设置标准输出 */ + var startInfo = new ProcessStartInfo(fileName, arguments) + { + RedirectStandardOutput = true + }; + + Process.Start(startInfo); + } + } + + public class Printer + { + /// + /// 当前是否正在打印 + /// + public static bool Printing = false; + + private static int rx1_handle = -1; + + public static int BoxStatus { get; set; } = (int)PrinterClient.BoxStatus.Normal; + + public static int Status + { + get + { + var value = GetStatus(); + + switch (value) + { + case PrinterStatus.Normal: + if (BoxStatus == (int)PrinterClient.BoxStatus.Download) + return (int)PrinterStatus.Waiting_For_File_Download; + else + return (int)PrinterStatus.Normal; + + default: + return (int)value; + } + } + } + + /* 序列号 */ + public static string Serial = ""; + + private static void FindSerial() + { + /* 获取打印机信息 */ + if (TaskDispatcher.ExecuteCommand("lpinfo", "-v", out string result)) + { + if (result.IndexOf("gutenprint52+usb://Dai+Nippon+Printing/Photo+Printer?serial=") == -1) + { + return; + } + + var arrays = result.Split(new char[] { '\r', '\n' }); + + var directs = arrays.ToList().FindAll(ar => ar.IndexOf("gutenprint52+usb://Dai+Nippon+Printing/Photo+Printer?serial=") != -1); + + string code = ""; + + foreach (var direct in directs) + { + int a = direct.LastIndexOf("serial="), b = direct.LastIndexOf("&backend"); + + if (a == -1 || b == -1) + continue; + + code = direct.Substring(a + 7, b - a - 7); + + if (code.IndexOf("NONE_UNKNOWN") != -1) + continue; + + break; + } + + if (code.Equals("NONE_UNKNOWN")) + Serial = ""; + else + Serial = code; + } + } + + private static PrinterStatus GetStatus() + { + PrinterStatus status = PrinterStatus.Normal; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (rx1_handle == -1) + rx1_handle = CyStatus.PortInitialize("USB001"); + + var res = CyStatus.GetStatus(rx1_handle); + + if (res == int.MinValue) + return PrinterStatus.DriveFailed; + else + { + switch (res) + { + case CyStatus.STATUS_USUALLY_IDLE: + return PrinterStatus.Normal; + case CyStatus.STATUS_USUALLY_PRINTING: + return PrinterStatus.Printing; + case CyStatus.STATUS_USUALLY_PAPER_END: + return PrinterStatus.NoPaper; + } + } + } + else + { + string result; + + /* 通过查找打印机序列号来判断打印机是否连接 */ + for (int i = 0; i < 6; i++) + { + FindSerial(); + if (!string.IsNullOrEmpty(Serial)) + break; + } + + if (string.IsNullOrEmpty(Serial)) + return PrinterStatus.NotDriven; + + /* 检查默认打印机 */ + for (int i = 0; i < 3; i++) + { + if (TaskDispatcher.ExecuteCommand("lpstat", "-d", out result)) + { + if (result.IndexOf("system default destination: DS-RX1HS") == -1) + { + /* 如果此时正在打印, 那么出现这种状况是有可能的, 先认为正常 */ + if(Printing) + return PrinterStatus.Normal; + else + Program.DebugWriteLine($"未找到默认打印机"); + } + else + { + status = PrinterStatus.Normal; + break; + } + } + + Thread.Sleep(10000); + } + + if (status == PrinterStatus.DriveFailed) + return status; + + /* 检查是否处于打印中的状态 */ + if (TaskDispatcher.ExecuteCommand("lpq", "", out result)) + { + //Console.WriteLine($"打印机当前状态:{status}"); + + if (!result.Contains("no entries")) + return PrinterStatus.Printing; + + } + + /* 检查打印机空闲状态 */ + if (TaskDispatcher.ExecuteCommand("lpstat", "-p", out result)) + { + if (result.IndexOf("printer DS-RX1HS is idle.") == -1) + { + /* 激活打印机 */ + TaskDispatcher.ExecuteCommand("cupsenable", "DS-RX1HS", out _); + /* 设置为接受作业 */ + TaskDispatcher.ExecuteCommand("cupsaccept", "DS-RX1HS", out _); + + return PrinterStatus.Sleep; + } + } + } + return status; + } + + /// + /// 删除任务 + /// + /// 工作序号 + public static void Delete(string job) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + TaskDispatcher.ExecuteCommand("lprm", job, out _); + } + } + + /// + /// 清空任务 + /// + public static void Clear() => Delete(""); + + /// + /// 获取打印队列 + /// + /// + public static List QueryEntries() + { + List lprEntries = new(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + if (TaskDispatcher.ExecuteCommand("lpq", "", out string result)) + { + lprEntries.Clear(); + + Console.WriteLine(result); + + if (result.Contains("no entries")) + return null; + + /* 根据文件查找job */ + var array = result.Split("\r\n"); + + for (int a = 2; a < array.Length; a++) + { + string temporary_data = ""; + List temporary_datas = new(); + for (int b = 0; b < array[a].Length; b++) + { + if (array[a][b] == ' ') + { + if (temporary_data != "") + { + temporary_datas.Add(temporary_data); + temporary_data = ""; + } + } + else + { + temporary_data += array[a][b]; + + if (b == array[a].Length - 1) + temporary_datas.Add(temporary_data); + } + } + + if (temporary_datas.Count == 6) + { + lprEntries.Add(new LprEntries() { Rank = temporary_datas[0], Owner = temporary_datas[1], Job = temporary_datas[2], File = temporary_datas[3], TotalSize = temporary_datas[4] + " " + temporary_datas[5] }); + } + } + } + } + + return lprEntries; + } + + /// + /// 打印 + /// + /// 文件 + /// + public static bool Print(string file_format_id, string print_mode_id, string print_size_id, string file, out string job) + { + job = string.Empty; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + CyStatus.SendFileToPrinter("DS-RX1", file); + + return true; + } + else + { + //TaskDispatcher.AsyncExecuteCommand("lpr", file); + + //TaskDispatcher.ExecuteCommand("PrintPhoto", $"DS-RX1HS {file}", out string result); + + string file_format = "TextGraphics", print_mode = "RGB", print_size = "B7"; + + switch (file_format_id) + { + case "29": file_format = "Text"; break; + case "30": file_format = "Graphics"; break; + case "31": file_format = "TextGraphics"; break; + case "32": file_format = "Photo"; break; + case "33": file_format = "LineArt"; break; + } + + switch (print_mode_id) + { + case "1": print_mode = "RGB"; break; + case "2": print_mode = "Gray"; break; + case "3": print_mode = "Black"; break; + case "4": print_mode = "CMY"; break; + case "5": print_mode = "CMYK"; break; + case "6": print_mode = "KCMY"; break; + } + + switch (print_size_id) + { + case "5": print_size = "B7"; break; + case "6": print_size = "w288h432"; break; + case "7": print_size = "w360h504"; break; + case "8": print_size = "A5"; break; + } + + TaskDispatcher.ExecuteCommand("./printer.sh", $"{file_format} {print_mode} {print_size} {file}", out string result); + + Console.WriteLine(result); + + if (file == "") + file = "(stdin)"; + + var lprEntries = QueryEntries(); + + int count = 3; + while (count-- > 0) + { + if (lprEntries.Count > 0) break; + + Thread.Sleep(10000); + + lprEntries = QueryEntries(); + } + + var enteries = lprEntries?.Find(ar => ar.File.Replace(".jpg", "").Equals(file.Replace(Program.ImagePath, "").Replace(".jpg", ""))); + + if (enteries != null) + { + job = enteries.Job; + + Console.WriteLine($"Rank = {enteries.Rank}, Job = {enteries.Job}, File = {enteries.File}, TotalSize = {enteries.TotalSize}"); + + return true; + } + } + + return false; + } + + public static void SetProperty(string name, string value) => TaskDispatcher.AsyncExecuteCommand("lpoptions", $"-o {name}={value}"); + + public static bool GetProperty(string name, out string value) + { + value = string.Empty; + + try + { + if (TaskDispatcher.ExecuteCommand("lpoptions", $"-l", out string result)) + { + result = result.Split(new char[] { '\n', '\r' }).ToList().Find(s => s.IndexOf(name) != -1); + + value = result.Split(' ').ToList().Find(s => s[0] == '*').Remove(0, 1); + + return true; + } + } + catch { } + + return false; + } + } + + public class LprEntries + { + public string Rank { get; set; } + public string Owner { get; set; } + public string Job { get; set; } + public string File { get; set; } + public string TotalSize { get; set; } + } +} diff --git a/PrinterClient/PrinterClient/Utils/ByteUtils.cs b/PrinterClient/PrinterClient/Utils/ByteUtils.cs new file mode 100644 index 0000000..f02411d --- /dev/null +++ b/PrinterClient/PrinterClient/Utils/ByteUtils.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Text; +using ProtoBuf; + +namespace PrinterClient +{ + public static class ByteUtils + { + public static byte[] Serialize(this T t) + { + using MemoryStream ms = new(); + Serializer.Serialize(ms, t); + return ms.ToArray(); + } + + public static T Deserialize(this byte[] content, int index, int count) + { + using MemoryStream ms = new(content, index, count); + return Serializer.Deserialize(ms); + } + + public static T Deserialize(this string content) + { + using MemoryStream ms = new(Encoding.UTF8.GetBytes(content)); + return Serializer.Deserialize(ms); + } + } +} + diff --git a/PrinterClient/PrinterClient/Utils/DeviceUtils.cs b/PrinterClient/PrinterClient/Utils/DeviceUtils.cs new file mode 100644 index 0000000..b02c031 --- /dev/null +++ b/PrinterClient/PrinterClient/Utils/DeviceUtils.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Net; +using System.Text; + +namespace PrinterClient.Utils +{ + public class DeviceUtils + { + public static string GetLocalIP() + { + string address = string.Empty; + using (Socket socket = new(AddressFamily.InterNetwork, SocketType.Dgram, 0)) + { + socket.Connect("8.8.8.8", 65530); + address = (socket.LocalEndPoint as IPEndPoint).Address.ToString(); + } + + return address; + } + } +} diff --git a/PrinterClient/PrinterClient/Utils/FileUtils.cs b/PrinterClient/PrinterClient/Utils/FileUtils.cs new file mode 100644 index 0000000..f4f06b6 --- /dev/null +++ b/PrinterClient/PrinterClient/Utils/FileUtils.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Text; + +namespace PrinterClient; + +public class FileUtils +{ + public static long Size(string fullpath) { try { return new FileInfo(fullpath).Length; } catch { return 0; } } + public static string GetName(string fullpath) { try { return new FileInfo(fullpath).Name; } catch { return ""; } } + public static string ReadString(string fullpath) { try { return File.ReadAllText(fullpath); } catch { return null; } } + public static byte[] ReadBytes(string fullpath) { try { return File.ReadAllBytes(fullpath); } catch { return new byte[] { }; } } + + public static void Append(string fullpath, string contents) + { + try + { + Directory.CreateDirectory(fullpath.Substring(0, fullpath.LastIndexOf("/"))); + + using FileStream fr = new FileStream(fullpath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + using StreamWriter sw = new StreamWriter(fr, Encoding.UTF8); + sw.WriteLine(contents); + } + catch { } + } + public static void Append(string fullpath, byte[] contents) + { + try + { + Directory.CreateDirectory(fullpath.Substring(0, fullpath.LastIndexOf("/"))); + + using FileStream fr = new FileStream(fullpath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + fr.Write(contents, 0, contents.Length); + } + catch { } + } + public static void Append(string fullpath, byte[] contents, int offset, int count) + { + try + { + Directory.CreateDirectory(fullpath.Substring(0, fullpath.LastIndexOf("/"))); + + using FileStream fr = new FileStream(fullpath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + fr.Write(contents, offset, count); + } + catch { } + } + + public static void WriteFile(string fullpath, string contents) + { + try + { + Directory.CreateDirectory(fullpath.Substring(0, fullpath.LastIndexOf("/"))); + + using FileStream fr = new FileStream(fullpath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + using StreamWriter sw = new StreamWriter(fr, Encoding.UTF8); + sw.WriteLine(contents); + } + catch { } + } + + + public static void WriteFile(string fullpath, byte[] contents) + { + try + { + Directory.CreateDirectory(fullpath.Substring(0, fullpath.LastIndexOf("/"))); + + using FileStream fr = new FileStream(fullpath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + fr.Write(contents, 0, contents.Length); + } + catch { } + } +} \ No newline at end of file diff --git a/PrinterClient/PrinterClient/Utils/LogUtils.cs b/PrinterClient/PrinterClient/Utils/LogUtils.cs new file mode 100644 index 0000000..b3c6a4e --- /dev/null +++ b/PrinterClient/PrinterClient/Utils/LogUtils.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; + +namespace PrinterClient; + +public class LogUtils +{ + public static string filepath { get; set; } = "Log"; + + public static void AppendLog(string message) + { + Console.WriteLine(message); + FileUtils.Append(Path.Combine(filepath, DateTime.Now.ToString("yyyyMMdd"), "Log.log"), $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} {message}"); + } + + public static void AppendLog(string filename, string message) + { + Console.WriteLine(message); + FileUtils.Append(Path.Combine(filepath, DateTime.Now.ToString("yyyyMMdd"), filename), $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} {message}"); + } + + public static void AppendError(string message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(message); + Console.ForegroundColor = ConsoleColor.White; + + FileUtils.Append(Path.Combine(filepath, DateTime.Now.ToString("yyyyMMdd"), "Error.log"), $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} {message}"); + } + + public static void AppendError(string filename, string message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(message); + Console.ForegroundColor = ConsoleColor.White; + + FileUtils.Append(Path.Combine(filepath, DateTime.Now.ToString("yyyyMMdd"), filename), $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} {message}"); + } + + + public static void AppendError(Exception ex) => AppendError($"exception Message:{ex.Message}, StackTrace:{ex.StackTrace}"); + + public static void AppendError(string filename, Exception ex) => AppendError(filename, $"exception Message:{ex.Message}, StackTrace:{ex.StackTrace}"); +} \ No newline at end of file diff --git a/PrinterClient/PrinterClient/Utils/TimerUtils.cs b/PrinterClient/PrinterClient/Utils/TimerUtils.cs new file mode 100644 index 0000000..8d322ed --- /dev/null +++ b/PrinterClient/PrinterClient/Utils/TimerUtils.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Concurrent; + +namespace PrinterClient +{ + public class TimerUtils + { + private static ConcurrentDictionary Records = new ConcurrentDictionary(); + + public static bool IsInterval(string name, double millsecond) + { + DateTime record = DateTime.MinValue; + + if (!Records.ContainsKey(name)) Records.TryAdd(name, DateTime.Now.AddMilliseconds(millsecond * -1)); + + if(Records.TryGetValue(name, out record)) + { + /* 时间发生异常改变时 */ + if (Math.Abs((DateTime.Now - record).TotalDays) > 1 || Math.Abs(DateTime.Now.Day - record.Day) >= 1) + { + Records.TryUpdate(name, DateTime.Now, record); + return false; + } + + if ((DateTime.Now - record).TotalMilliseconds > millsecond) + { + Records.TryUpdate(name, DateTime.Now, record); + return true; + } + else + return false; + + } + else return false; + } + } +} + diff --git a/PrinterClient/PrinterClient/app.config b/PrinterClient/PrinterClient/app.config new file mode 100644 index 0000000..6b84cf3 --- /dev/null +++ b/PrinterClient/PrinterClient/app.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/PrinterClient/PrinterClient/protocol.cs b/PrinterClient/PrinterClient/protocol.cs new file mode 100644 index 0000000..9a53c50 --- /dev/null +++ b/PrinterClient/PrinterClient/protocol.cs @@ -0,0 +1,351 @@ +// This file was generated by a tool; you should avoid making direct changes. +// Consider using 'partial classes' to extend these types +// Input: protocol.proto + +#pragma warning disable CS1591, CS0612, CS3021 + +namespace Google.Protobuf.WellKnownTypes +{ + + [global::ProtoBuf.ProtoContract()] + public partial class CommonResponse + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3, Name = @"status")] + [global::System.ComponentModel.DefaultValue("")] + public string Status { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"remark")] + [global::System.ComponentModel.DefaultValue("")] + public string Remark { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalStateUpdate + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipType { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"longitude")] + [global::System.ComponentModel.DefaultValue("")] + public string Longitude { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5, Name = @"latitude")] + [global::System.ComponentModel.DefaultValue("")] + public string Latitude { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(6)] + [global::System.ComponentModel.DefaultValue("")] + public string equipVer { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(7)] + [global::System.ComponentModel.DefaultValue("")] + public string equipTime { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(8, Name = @"ip")] + [global::System.ComponentModel.DefaultValue("")] + public string Ip { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(9)] + [global::System.ComponentModel.DefaultValue("")] + public string equipStatus { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(10)] + [global::System.ComponentModel.DefaultValue("")] + public string printerStatus { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(11)] + [global::System.ComponentModel.DefaultValue("")] + public string peripheralFeatureIds { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(12)] + [global::System.ComponentModel.DefaultValue("")] + public string printerCode { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalPrintTaskState + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string printOrderCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"status")] + [global::System.ComponentModel.DefaultValue("")] + public string Status { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5)] + [global::System.ComponentModel.DefaultValue("")] + public string printerStatus { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalPrintTask + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string printOrderCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue("")] + public string fileFormatId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5)] + [global::System.ComponentModel.DefaultValue("")] + public string printModeId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(6)] + [global::System.ComponentModel.DefaultValue("")] + public string mediaTypeId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(7)] + [global::System.ComponentModel.DefaultValue("")] + public string printTypeId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(8)] + [global::System.ComponentModel.DefaultValue("")] + public string copyCount { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(9)] + [global::System.ComponentModel.DefaultValue("")] + public string borderlessTypeId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(10)] + [global::System.ComponentModel.DefaultValue("")] + public string printFileUrl { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(11)] + [global::System.ComponentModel.DefaultValue("")] + public string printSizeId { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(12)] + [global::System.ComponentModel.DefaultValue("")] + public string printPageNumber { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalPrintTaskResult + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string printOrderCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"status")] + [global::System.ComponentModel.DefaultValue("")] + public string Status { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5, Name = @"remark")] + [global::System.ComponentModel.DefaultValue("")] + public string Remark { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalCheckVersion + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3, Name = @"type")] + [global::System.ComponentModel.DefaultValue("")] + public string Type { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue("")] + public string versionCode { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalCheckVersionResult + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string versionCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue("")] + public string versionName { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5, Name = @"type")] + [global::System.ComponentModel.DefaultValue("")] + public string Type { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(6)] + [global::System.ComponentModel.DefaultValue("")] + public string verUrl { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalControl + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string orderCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"type")] + [global::System.ComponentModel.DefaultValue("")] + public string Type { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class TerminalControlUpdate + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string equipNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string equipCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string orderCode { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(4, Name = @"type")] + [global::System.ComponentModel.DefaultValue("")] + public string Type { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(5, Name = @"status")] + [global::System.ComponentModel.DefaultValue("")] + public string Status { get; set; } = ""; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class PrintMessage + { + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue("")] + public string serialNo { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(2, Name = @"source")] + [global::System.ComponentModel.DefaultValue("")] + public string Source { get; set; } = ""; + + [global::ProtoBuf.ProtoMember(3)] + public TaskType ecsType { get; set; } + + [global::ProtoBuf.ProtoMember(4)] + public CommonResponse commandResponse { get; set; } + + [global::ProtoBuf.ProtoMember(5)] + public TerminalStateUpdate terminalStateUpdate { get; set; } + + [global::ProtoBuf.ProtoMember(6)] + public TerminalPrintTaskState terminalPrintTaskState { get; set; } + + [global::ProtoBuf.ProtoMember(7)] + public TerminalPrintTask terminalPrintTask { get; set; } + + [global::ProtoBuf.ProtoMember(8)] + public TerminalPrintTaskResult terminalPrintTaskResult { get; set; } + + [global::ProtoBuf.ProtoMember(9)] + public TerminalCheckVersion terminalCheckVersion { get; set; } + + [global::ProtoBuf.ProtoMember(10)] + public TerminalCheckVersionResult terminalCheckVersionResult { get; set; } + + [global::ProtoBuf.ProtoMember(11)] + public TerminalControl terminalControl { get; set; } + + [global::ProtoBuf.ProtoMember(12)] + public TerminalControlUpdate terminalControlUpdate { get; set; } + + } + + [global::ProtoBuf.ProtoContract()] + public enum TaskType + { + [global::ProtoBuf.ProtoEnum(Name = @"COMMON_RESPONSE")] + CommonResponse = 0, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_STATE_UPDATE")] + TerminalStateUpdate = 1, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_PRINTTASK_STATE")] + TerminalPrinttaskState = 2, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_PRINTTASK")] + TerminalPrinttask = 3, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_PRINTTASK_RESULT")] + TerminalPrinttaskResult = 4, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_CHECKVERSION")] + TerminalCheckversion = 5, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_CHECKVERSION_RESULT")] + TerminalCheckversionResult = 6, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_CONTROL")] + TerminalControl = 7, + [global::ProtoBuf.ProtoEnum(Name = @"TERMINAL_CONTROL_UPDATE")] + TerminalControlUpdate = 8, + } + +} + +#pragma warning restore CS1591, CS0612, CS3021 diff --git a/PrinterClient/物联平台-终端打印盒子TCP协议V1.0.4.docx b/PrinterClient/物联平台-终端打印盒子TCP协议V1.0.4.docx new file mode 100644 index 0000000000000000000000000000000000000000..2530799ff7244d1f67917167b7ded0fa7df3bf54 GIT binary patch literal 43161 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

@+`$}RB4k? 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 + + + + + diff --git a/TestView/TestView/App.xaml b/TestView/TestView/App.xaml new file mode 100644 index 0000000..1ea2fdb --- /dev/null +++ b/TestView/TestView/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/TestView/TestView/App.xaml.cs b/TestView/TestView/App.xaml.cs new file mode 100644 index 0000000..b7c8b2f --- /dev/null +++ b/TestView/TestView/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace TestView +{ + ///

+ /// App.xaml 的交互逻辑 + /// + public partial class App : Application + { + } +} diff --git a/TestView/TestView/FodyWeavers.xml b/TestView/TestView/FodyWeavers.xml new file mode 100644 index 0000000..882317c --- /dev/null +++ b/TestView/TestView/FodyWeavers.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/TestView/TestView/FodyWeavers.xsd b/TestView/TestView/FodyWeavers.xsd new file mode 100644 index 0000000..ff119f7 --- /dev/null +++ b/TestView/TestView/FodyWeavers.xsd @@ -0,0 +1,141 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Controls if runtime assemblies are also embedded. + + + + + Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/TestView/TestView/Loading.xaml b/TestView/TestView/Loading.xaml new file mode 100644 index 0000000..20c3aa4 --- /dev/null +++ b/TestView/TestView/Loading.xaml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestView/TestView/Loading.xaml.cs b/TestView/TestView/Loading.xaml.cs new file mode 100644 index 0000000..8f0d804 --- /dev/null +++ b/TestView/TestView/Loading.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace TestView +{ + /// + /// Loading.xaml 的交互逻辑 + /// + public partial class Loading : UserControl + { + public Loading() + { + InitializeComponent(); + } + } +} diff --git a/TestView/TestView/MainWindow.xaml b/TestView/TestView/MainWindow.xaml new file mode 100644 index 0000000..91afd13 --- /dev/null +++ b/TestView/TestView/MainWindow.xaml @@ -0,0 +1,90 @@ + + + + + + + + + + + +