Commit 3f45ba3e 张东亮

init

0 个父辈
正在显示 116 个修改的文件 包含 12690 行增加0 行删除
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
\ No newline at end of file \ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30523.141
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "source\Common\Common.csproj", "{43CDD09E-FCF3-4960-A01D-3BBFE9933122}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceLibrary", "source\DeviceLibrary\DeviceLibrary.csproj", "{513BC1C9-800D-43A6-9499-3700BAEC3554}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserFromControl", "source\UserFromControl\UserFromControl.csproj", "{F018462A-D9BC-4365-97F2-F6D71751641E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadCSVLibrary", "source\LoadCVSLibrary\LoadCSVLibrary.csproj", "{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmptyShelfLine", "source\EmptyShelfLine\EmptyShelfLine.csproj", "{0D2542F5-DD62-4352-82D0-383D9A045E74}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{43CDD09E-FCF3-4960-A01D-3BBFE9933122}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43CDD09E-FCF3-4960-A01D-3BBFE9933122}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43CDD09E-FCF3-4960-A01D-3BBFE9933122}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43CDD09E-FCF3-4960-A01D-3BBFE9933122}.Release|Any CPU.Build.0 = Release|Any CPU
{513BC1C9-800D-43A6-9499-3700BAEC3554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{513BC1C9-800D-43A6-9499-3700BAEC3554}.Debug|Any CPU.Build.0 = Debug|Any CPU
{513BC1C9-800D-43A6-9499-3700BAEC3554}.Release|Any CPU.ActiveCfg = Release|Any CPU
{513BC1C9-800D-43A6-9499-3700BAEC3554}.Release|Any CPU.Build.0 = Release|Any CPU
{F018462A-D9BC-4365-97F2-F6D71751641E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F018462A-D9BC-4365-97F2-F6D71751641E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F018462A-D9BC-4365-97F2-F6D71751641E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F018462A-D9BC-4365-97F2-F6D71751641E}.Release|Any CPU.Build.0 = Release|Any CPU
{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}.Debug|Any CPU.Build.0 = Debug|Any CPU
{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}.Release|Any CPU.ActiveCfg = Release|Any CPU
{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}.Release|Any CPU.Build.0 = Release|Any CPU
{0D2542F5-DD62-4352-82D0-383D9A045E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D2542F5-DD62-4352-82D0-383D9A045E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D2542F5-DD62-4352-82D0-383D9A045E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D2542F5-DD62-4352-82D0-383D9A045E74}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5459501E-8250-488F-B563-3C6777AEFCBA}
EndGlobalSection
EndGlobal
文件属性发生变化
此文件类型无法预览
<?xml version="1.0"?>
<doc>
<assembly>
<name>Asa.IOModule.AIOBOX</name>
</assembly>
<members>
<member name="T:Asa.IOModule.AIOBOX">
<summary>
AIOBOX操作类
</summary>
</member>
<member name="F:Asa.IOModule.AIOBOX.SEND_SLEEP">
<summary>
每条命令发送的间隔
不能小于15,会出现IO接收不到的情况
小于30时,会出现接收数据连包的情况
</summary>
</member>
<member name="F:Asa.IOModule.AIOBOX.PORT">
<summary>
ModBus端口
</summary>
</member>
<member name="T:Asa.IOModule.AIOBOX.DIO_Changed">
<summary>
自动读取DI委托
</summary>
<param name="box">AIOBOX</param>
<param name="sta">所有DI状态</param>
</member>
<member name="E:Asa.IOModule.AIOBOX.DI_Changed_Event">
<summary>
自动读取DI事件触发
</summary>
</member>
<member name="E:Asa.IOModule.AIOBOX.DO_Changed_Event">
<summary>
自动读取DO事件触发
</summary>
</member>
<member name="T:Asa.IOModule.AIOBOX.AIO_Changed">
<summary>
自动读取AI委托
</summary>
<param name="box">AIOBOX</param>
<param name="val">所有AI的值</param>
</member>
<member name="E:Asa.IOModule.AIOBOX.AI_Changed_Event">
<summary>
自动读取AI事件触发
</summary>
</member>
<member name="E:Asa.IOModule.AIOBOX.AO_Changed_Event">
<summary>
自动读取AO事件触发
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.#ctor">
<summary>
AIOBOX
</summary>
</member>
<member name="P:Asa.IOModule.AIOBOX.IP">
<summary>
IP地址
</summary>
</member>
<member name="P:Asa.IOModule.AIOBOX.IsConn">
<summary>
是否连接
</summary>
</member>
<member name="P:Asa.IOModule.AIOBOX.ErrInfo">
<summary>
错误信息
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.LogPath(System.String,Asa.IOModule.LogType)">
<summary>
日志路径,连接前设置路径会自动保存日志
</summary>
<param name="path">文件夹路径</param>
<param name="type">输出类型</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.SetInput(Asa.IOModule.Box_Type,System.Int32)">
<summary>
设置输入端
</summary>
<param name="type">类型</param>
<param name="count">数量</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.SetOutput(Asa.IOModule.Box_Type,System.Int32)">
<summary>
设置输出端
</summary>
<param name="type">类型</param>
<param name="count">数量</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoIP(System.String)">
<summary>
自动获取IP地址,未连接前使用,必须在同一网段
</summary>
<param name="localIP">本地IP地址</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.CheckIP(System.String)">
<summary>
检查IP地址
</summary>
<param name="ip"></param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.Connect">
<summary>
连接
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.Close">
<summary>
关闭连接
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoReadInput(System.Boolean,System.Int32)">
<summary>
自动读取输入端并触发事件(主动上传数据 = 禁止)
</summary>
<param name="read">是否自动读取</param>
<param name="sleep">间隔,必须大于等于15ms</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoReadInput(System.Boolean)">
<summary>
自动读取输入端并触发事件(主动上传数据 = 使能)
</summary>
<param name="read">是否自动读取</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoReadOutput(System.Boolean,System.Int32)">
<summary>
自动读取输出端,触发事件
</summary>
<param name="read">是否自动读取</param>
<param name="sleep">间隔,必须大于等于15ms</param>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReverseStatus(Asa.IOModule.Box_Sta)">
<summary>
相反状态(ON/OFF)
</summary>
<param name="sta"></param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReverseStatus(Asa.IOModule.Box_Sta@)">
<summary>
相反状态(ON/OFF)
</summary>
<param name="sta"></param>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDI(System.Int32)">
<summary>
读取单个DI输入状态(ON/OFF)
</summary>
<param name="add">输入地址,从0开始</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDI(System.Int32,System.Int32)">
<summary>
读取多个DI输入状态(ON/OFF)
</summary>
<param name="add">起始地址,从0开始</param>
<param name="count">数量</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadAI(System.Int32)">
<summary>
读取单个AI模拟量的值
</summary>
<param name="add">模拟量地址,从0开始</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadAI(System.Int32,System.Int32)">
<summary>
读取多个AI模拟量的值
</summary>
<param name="add">起始地址,从0开始</param>
<param name="count">数量</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDO(System.Int32)">
<summary>
读取单个DO输出状态(ON/OFF)
</summary>
<param name="add">输出地址,从0开始</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDO(System.Int32,System.Int32)">
<summary>
读取多个DO输出状态(ON/OFF)
</summary>
<param name="add">起始地址,从0开始</param>
<param name="count">数量</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadAO(System.Int32)">
<summary>
读取单个AO模拟量的值
</summary>
<param name="add">输出地址,从0开始</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadAO(System.Int32,System.Int32)">
<summary>
读取多个AO模拟量的值
</summary>
<param name="add">起始地址,从0开始</param>
<param name="count">数量</param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.WriteDO(System.Int32,Asa.IOModule.Box_Sta)">
<summary>
写入单个DO输出状态(ON/OFF)
</summary>
<param name="add">输出地址,从0开始</param>
<param name="sta"></param>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.GetLocalIP">
<summary>
获取本地IPv4地址
</summary>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.Send">
<summary>
发送命令
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.Receive">
<summary>
接收命令
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadSingle(System.Byte[])">
<summary>
读取写入单个DO,功能码5
</summary>
<param name="buff"></param>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDO(System.Byte[])">
<summary>
读取所有DO状态,功能码1
</summary>
<param name="buff"></param>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadDI(System.Byte[])">
<summary>
读取所有DI状态,功能码2
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.ReadAI(System.Byte[])">
<summary>
读取所有AI的值,功能码4
</summary>
<param name="buff"></param>
</member>
<member name="M:Asa.IOModule.AIOBOX.Command">
<summary>
命令,前7个字节
</summary>
<returns></returns>
</member>
<member name="M:Asa.IOModule.AIOBOX.TriggerDIO">
<summary>
触发DIO改变事件
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoReadInput">
<summary>
自动读取输入端线程
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.AutoReadOutput">
<summary>
自动读取输出端线程
</summary>
</member>
<member name="M:Asa.IOModule.AIOBOX.Listen">
<summary>
监听结果线程
</summary>
</member>
<member name="T:Asa.IOModule.Box_Type">
<summary>
IO模块类型
</summary>
</member>
<member name="F:Asa.IOModule.Box_Type.DI">
<summary>
数字信号输入
</summary>
</member>
<member name="F:Asa.IOModule.Box_Type.DO">
<summary>
数字信号输出
</summary>
</member>
<member name="F:Asa.IOModule.Box_Type.AI">
<summary>
模拟量输入
</summary>
</member>
<member name="F:Asa.IOModule.Box_Type.AO">
<summary>
模拟量输出
</summary>
</member>
<member name="T:Asa.IOModule.Box_Sta">
<summary>
IO模块寄存器状态
</summary>
</member>
<member name="F:Asa.IOModule.Box_Sta.Off">
<summary>
断开,关闭,低电平
</summary>
</member>
<member name="F:Asa.IOModule.Box_Sta.On">
<summary>
闭合,打开,高电平
</summary>
</member>
<member name="T:Asa.IOModule.LogType">
<summary>
日志类型
</summary>
</member>
<member name="F:Asa.IOModule.LogType.OnlyError">
<summary>
仅错误信息
</summary>
</member>
<member name="F:Asa.IOModule.LogType.All">
<summary>
所有
</summary>
</member>
<member name="T:Asa.IOModule.LogFile">
<summary>
日志操作类
</summary>
</member>
<member name="M:Asa.IOModule.LogFile.#ctor(System.String,System.String)">
<summary>
日志
</summary>
<param name="path">文件夹路径</param>
<param name="ip"></param>
</member>
<member name="M:Asa.IOModule.LogFile.Close">
<summary>
关闭文件
</summary>
</member>
<member name="M:Asa.IOModule.LogFile.OutError(System.String)">
<summary>
输出错误
</summary>
<param name="s"></param>
</member>
<member name="M:Asa.IOModule.LogFile.OutInfo(System.String)">
<summary>
输出信息
</summary>
<param name="s"></param>
</member>
<member name="M:Asa.IOModule.LogFile.OutData(System.String,System.Byte[])">
<summary>
输出数据
</summary>
<param name="tr"></param>
<param name="buff"></param>
</member>
<member name="M:Asa.IOModule.LogFile.OutData(System.String)">
<summary>
输出数据
</summary>
<param name="s"></param>
</member>
</members>
</doc>
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
<?xml version="1.0"?>
<doc>
<assembly>
<name>Client</name>
</assembly>
<members>
<member name="T:Asa.Client">
<summary>
电脑客户端
</summary>
</member>
<member name="F:Asa.Client.HEART">
<summary>
心跳包,HEART
</summary>
</member>
<member name="F:Asa.Client.SERVER_OFF">
<summary>
服务器关闭,OFF
</summary>
</member>
<member name="F:Asa.Client.CLIENT_OFF">
<summary>
客户端关闭,OFF
</summary>
</member>
<member name="T:Asa.Client.ActionEvent">
<summary>
小车动作事件
</summary>
</member>
<member name="E:Asa.Client.GetRFID">
<summary>
服务端发送的RFID
</summary>
</member>
<member name="E:Asa.Client.Arrive">
<summary>
小车到达,仅包装料仓
</summary>
</member>
<member name="E:Asa.Client.Ready">
<summary>
小车已准备,对接完成
</summary>
</member>
<member name="E:Asa.Client.CanEnter">
<summary>
能否进入,仅流水线
</summary>
</member>
<member name="T:Asa.Client.LogEvent">
<summary>
日志事件
</summary>
<param name="s"></param>
</member>
<member name="E:Asa.Client.Log">
<summary>
日志
</summary>
</member>
<member name="P:Asa.Client.IsConn">
<summary>
是否连接服务器
</summary>
</member>
<member name="P:Asa.Client.RFID">
<summary>
RFID的内容
</summary>
</member>
<member name="M:Asa.Client.#ctor(System.String)">
<summary>
电脑客户端
</summary>
<param name="serverIP">服务器IP地址</param>
</member>
<member name="M:Asa.Client.Connect(System.String[])">
<summary>
连接
</summary>
<param name="id"></param>
</member>
<member name="M:Asa.Client.Close">
<summary>
关闭
</summary>
</member>
<member name="M:Asa.Client.SendRFID(System.String,System.String)">
<summary>
发送RFID信息
</summary>
<param name="id"></param>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.NeedEnter(System.String,System.String)">
<summary>
需要进入料架(包装料仓)
</summary>
<param name="id"></param>
<param name="mark"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.NeedLeave(System.String)">
<summary>
需要出料架
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.MayEnter(System.String)">
<summary>
可以进入
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.FinishEnter(System.String)">
<summary>
完成进入
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.MayLeave(System.String)">
<summary>
可以出去
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.FinishLeave(System.String)">
<summary>
完成出去
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.IsEnter(System.String)">
<summary>
是否可以进入,仅用于CanEnter事件
</summary>
<param name="id">节点,可以多个</param>
<returns></returns>
</member>
<member name="M:Asa.Client.Send(System.Byte[])">
<summary>
发送命令
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.HexBuff(System.Byte[])">
<summary>
16进制
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.ListenNet">
<summary>
监听线程
</summary>
</member>
<member name="M:Asa.Client.Resolve">
<summary>
分析数据包
</summary>
</member>
<member name="M:Asa.Client.Splice(System.Byte,System.String,System.Byte[])">
<summary>
拼接命令
</summary>
<param name="code"></param>
<param name="id"></param>
<param name="content"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.CheckRemoteIP(System.String)">
<summary>
检查远程IP地址
</summary>
<param name="ip"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.IsHeart(System.Byte[])">
<summary>
是否心跳包
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client.IsServerOffline(System.Byte[])">
<summary>
是否服务器断开
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="T:Asa.Client2">
<summary>
电脑客户端
</summary>
</member>
<member name="F:Asa.Client2.HEART">
<summary>
心跳包,HEART
</summary>
</member>
<member name="F:Asa.Client2.SERVER_OFF">
<summary>
服务器关闭,OFF
</summary>
</member>
<member name="F:Asa.Client2.CLIENT_OFF">
<summary>
客户端关闭,OFF
</summary>
</member>
<member name="T:Asa.Client2.ActionEvent">
<summary>
小车动作事件
</summary>
</member>
<member name="T:Asa.Client2.LogEvent">
<summary>
日志事件
</summary>
<param name="s"></param>
</member>
<member name="E:Asa.Client2.Arrive">
<summary>
小车到达,仅包装料仓
</summary>
</member>
<member name="E:Asa.Client2.Ready">
<summary>
小车已准备,对接完成
</summary>
</member>
<member name="E:Asa.Client2.CloseDoor">
<summary>
关门,仅包装料仓
</summary>
</member>
<member name="E:Asa.Client2.EnterShelf">
<summary>
准备进入料架不能出料,仅包装料仓
</summary>
</member>
<member name="E:Asa.Client2.Log">
<summary>
日志
</summary>
</member>
<member name="M:Asa.Client2.#ctor(System.String)">
<summary>
电脑客户端
</summary>
<param name="serverIP">服务器IP地址</param>
</member>
<member name="P:Asa.Client2.IsConn">
<summary>
是否连接服务器
</summary>
</member>
<member name="P:Asa.Client2.CancelState">
<summary>
取消状态,true发送none,false发送实际状态
</summary>
</member>
<member name="P:Asa.Client2.SendLog">
<summary>
发送命令的日志是否打印,不影响其他日志
</summary>
</member>
<member name="P:Asa.Client2.SendSleep">
<summary>
发送命令的时间间隔(单位:秒)
</summary>
</member>
<member name="M:Asa.Client2.Connect">
<summary>
连接
</summary>
</member>
<member name="M:Asa.Client2.Close">
<summary>
关闭
</summary>
</member>
<member name="M:Asa.Client2.SetStatus(System.String,System.String,System.String,Asa.ClientAction,Asa.ClientLevel)">
<summary>
设置状态
</summary>
<param name="name">节点名称</param>
<param name="mark">节点标记</param>
<param name="rfid">架子RFID</param>
<param name="action"></param>
<param name="level"></param>
</member>
<member name="M:Asa.Client2.Splice(Asa.ClientNode)">
<summary>
拼接命令
</summary>
<param name="node"></param>
<returns></returns>
</member>
<member name="M:Asa.Client2.ListenNet">
<summary>
监听线程
</summary>
</member>
<member name="M:Asa.Client2.Resolve">
<summary>
分析数据包
</summary>
</member>
<member name="M:Asa.Client2.Send(System.Byte[])">
<summary>
发送命令
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client2.HexBuff(System.Byte[])">
<summary>
16进制
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client2.IsHeart(System.Byte[])">
<summary>
是否心跳包
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="M:Asa.Client2.IsServerOffline(System.Byte[])">
<summary>
是否服务器断开
</summary>
<param name="buff"></param>
<returns></returns>
</member>
<member name="T:Asa.ClientNode">
<summary>
客户端的节点
</summary>
</member>
<member name="F:Asa.ClientNode.Name">
<summary>
节点名称
</summary>
</member>
<member name="F:Asa.ClientNode.Mark">
<summary>
标记,用于包装料仓
</summary>
</member>
<member name="F:Asa.ClientNode.RFID">
<summary>
当前架子的RFID
</summary>
</member>
<member name="F:Asa.ClientNode.Action">
<summary>
动作
</summary>
</member>
<member name="F:Asa.ClientNode.Level">
<summary>
优先级
</summary>
</member>
<member name="M:Asa.ClientNode.#ctor(System.String,System.String,System.String,Asa.ClientAction,Asa.ClientLevel)">
<summary>
客户端节点
</summary>
<param name="name"></param>
<param name="mark"></param>
<param name="rfid"></param>
<param name="action"></param>
<param name="level"></param>
</member>
<member name="T:Asa.ClientAction">
<summary>
客户端的动作
</summary>
</member>
<member name="F:Asa.ClientAction.None">
<summary>
没有动作
</summary>
</member>
<member name="F:Asa.ClientAction.CloseDoor">
<summary>
包装料仓关门
</summary>
</member>
<member name="F:Asa.ClientAction.MayEnter">
<summary>
可以进入料架,Arrive事件使用,让小车开始对接
</summary>
</member>
<member name="F:Asa.ClientAction.MayLeave">
<summary>
可以出去料架,Arrive事件使用,让小车开始对接
</summary>
</member>
<member name="F:Asa.ClientAction.NeedEnter">
<summary>
需要进入料架
</summary>
</member>
<member name="F:Asa.ClientAction.NeedLeave">
<summary>
需要出去料架
</summary>
</member>
<member name="F:Asa.ClientAction.FinishEnter">
<summary>
完成进入料架
</summary>
</member>
<member name="F:Asa.ClientAction.FinishLeave">
<summary>
完成出去料架
</summary>
</member>
<member name="F:Asa.ClientAction.Arrive">
<summary>
小车到达,到达包装料仓门口,等待开门
</summary>
</member>
<member name="F:Asa.ClientAction.Ready">
<summary>
小车已准备,已对接上流水线
</summary>
</member>
<member name="F:Asa.ClientAction.EnterShelf">
<summary>
包装料仓只能入料不能出料
</summary>
</member>
<member name="T:Asa.ClientLevel">
<summary>
客户端的优先级
</summary>
</member>
<member name="F:Asa.ClientLevel.Low">
<summary>
</summary>
</member>
<member name="F:Asa.ClientLevel.Middle">
<summary>
中等
</summary>
</member>
<member name="F:Asa.ClientLevel.High">
<summary>
</summary>
</member>
</members>
</doc>
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
文件属性发生变化
文件属性发生变化
此文件类型无法预览
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{43CDD09E-FCF3-4960-A01D-3BBFE9933122}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OnlineStore.Common</RootNamespace>
<AssemblyName>Common</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\dll\log4net.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\dll\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="bean\Bean.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Setting_Init.cs" />
<Compile Include="util\ConfigAppSettings.cs" />
<Compile Include="util\FormUtil.cs" />
<Compile Include="util\HttpHelper.cs" />
<Compile Include="util\JsonHelper.cs" />
<Compile Include="util\LogUtil.cs" />
<Compile Include="util\MyWebClient.cs">
<SubType>Component</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file \ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("Common")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Common")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("f8eab140-5f98-4df7-842c-0d866e759c9a")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.Common
{
/// <summary>
/// 记录配置的key
/// </summary>
public class Setting_Init
{
public static string Server_Log_Open = "Server_Log_Open";
/// <summary>
/// 系统启动时自动启动VMI流水线,=1时自动启动,并隐藏窗口,=0时不需要
/// </summary>
public static string App_AutoRun = "App_AutoRun";
/// <summary>
/// 系统主界面标题
/// </summary>
public static string App_Title = "App_Title";
public static string http_server = "http.server";
public static string Line_Config = "Line_Config";
public static string UseAIOBOX = "UseAIOBOX";
/// <summary>
/// 是否调试状态
/// </summary>
public static string IsInDebug = "IsInDebug";
public static string AgvServerIp = "AgvServerIp";
public static string Agv_Log_Open = "Agv_Log_Open";
public static string RfidServer_Port = "RfidServer_Port";
}
}
文件属性发生变化
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.Common
{
/// <summary>
/// 与服务器通信用对象
/// </summary>
public class Operation
{
/// <summary>
/// VMI流水线唯一标识
/// </summary>
private string _cid = "";
public string cid
{
get { return _cid; }
set { _cid = value; }
}
/// <summary>
/// 请求序列号
/// </summary>
public int seq { get; set; }
/// <summary>
/// 操作码(0无操作(发送VMI流水线状态给服务器),
/// 1扫码入库(扫码成功后发送给服务器),
/// 2 出库(服务器发送),3表示错误信息 )
/// 4,发送给服务表示二维码扫码入库,收到开始扫码
/// </summary>
public int op { get; set; }
/// <summary>
/// 操作相关数据,
/// op=1时,客户端发送 code 二维码给服务器,服务器返回时有:posId库位编号,plateW:料盘宽度,plateH:料盘高度
/// 如果需要更新温湿度的报警值,服务器会发送alarmTemperature,alarmHumidity给客户端,客户端缓存,如果没有发送,不处理
/// op=3时,data发送BoxID和AlarmCode
/// =4时扫码入库
/// =5时服务器发送预警温度
/// </summary>
private Dictionary<string, string> _data = new Dictionary<string, string>();
public Dictionary<string, string> data
{
get { return _data; }
set { _data = value; }
}
/// <summary>
/// 整体VMI流水线状态
/// 1=正常运行中
/// 2=急停中
/// 3=故障(气压检测不到等,用msg发送详细故障说明)
/// 4=警告(用msg发送提醒,如出库到达工位但是没有工人操作)
/// </summary>
public int status { get; set; }
/// <summary>
/// 提示消息
/// 出入库错误: BOX正在调试中,不能出入库
/// 出入库错误: 急停了不能出入库
/// 入库错误:料盘过大,放不到指定的位置中去
/// 故障:气压信号检测不到
/// 警告:出库盘到达工位但是没有工人操作
/// </summary>
public string msg { get; set; }
/// <summary>
/// 包含的多个 BOX 的状态信息
/// </summary>
public Dictionary<int, BoxStatus> boxStatus = new Dictionary<int, BoxStatus>();
/// <summary>
/// 报警集合
/// </summary>
public List<AlarmInfo> alarmList = new List<AlarmInfo>();
}
/// <summary>
/// 单台VMI流水线状态(包含流水线)
/// </summary>
public class BoxStatus
{
/// <summary>
/// Box编号,从1开始
/// </summary>
public int boxId { get; set; }
/// <summary>
/// 单台BOX状态
/// 急停,故障,调试中,就绪状态(正常待机)
/// 入库执行中,入库完成,入库失败
/// 出库执行中,出库完成,出库失败
/// </summary>
public int status { get; set; }
/// <summary>
/// 单台BOX的消息
/// 正在调试中,不能出入库
/// 入库失败原因:
/// 出库失败原因:
/// </summary>
public string msg { get; set; }
/// <summary>
/// 温度
/// </summary>
public string temperature { get; set; }
/// <summary>
/// 湿度
/// </summary>
public string humidity { get; set; }
/// <summary>
/// 操作相关数据,
/// 出库完成后发送posId库位编号给服务器
/// </summary>
private Dictionary<string, string> _data = new Dictionary<string, string>();
public Dictionary<string, string> data
{
get { return _data; }
set { _data = value; }
}
}
public class AlarmInfo
{
public AlarmInfo(int StoreID, int aType, string alarmDetial, string WarnMsg, int inoutStatus)
{
// TODO: Complete member initialization
this.boxId = StoreID;
this.alarmType = aType;
this.alarmDetail = alarmDetial;
this.alarmMsg = WarnMsg;
this.inOutStatus = inoutStatus;
}
public AlarmInfo()
{
// TODO: Complete member initialization
}
/// <summary>
/// VMI流水线ID,0表示流水线
/// </summary>
public int boxId { get; set; }
/// <summary>
/// 报警类型,
/// </summary>
public int alarmType { get; set; }
/// <summary>
/// 报警详情
///AlarmType= 0 消息 "1=原点返回
//AlarmType= 0 消息 2=复位"
//AlarmType=1 总体错误 "1=急停
//AlarmType=1 总体错误 2=没有气压信号
//AlarmType=1 总体错误,3=盘错乱"
//AlarmType=2 运动轴错误 1=第一轴(旋转)
//AlarmType=2 运动轴错误 2=第二轴(上下轴)
//AlarmType=2 运动轴错误 3=第三轴(前进轴)
//AlarmType=2 运动轴错误 4=第四轴(压紧轴)"
//AlarmType=2 电钢报警 5=上下电钢
//AlarmType=3 IO报警,信号超时 io电器定义(电器定义)
/// </summary>
public string alarmDetail { get; set; }
/// <summary>
/// 报警消息
/// </summary>
public string alarmMsg { get; set; }
/// <summary>
/// 0,1=入库,2=出库
/// </summary>
public int inOutStatus { get; set; }
}
public class ParamDefine
{
/// <summary>
/// 库位 ID
/// </summary>
public static string posId = "posId";
/// <summary>
/// 料盘宽
/// </summary>
public static string plateW = "plateW";
/// <summary>
/// 料盘高
/// </summary>
public static string plateH = "plateH";
/// <summary>
/// VMI流水线ID
/// </summary>
public static string storeId = "storeId";
/// <summary>
/// 报警码
/// </summary>
public static string alarmCode = "alarmCode";
/// <summary>
/// 报警详情或参数
/// </summary>
public static string alarmDetial = "alarmDetial";
/// <summary>
/// 湿度报警值
/// </summary>
public static string maxHumidity = "humi";
/// <summary>
/// 温度报警值
/// </summary>
public static string maxTemperature = "temp";
/// <summary>
/// urgentReel: true 表示紧急料,需要出到料串上
/// </summary>
public static string urgentReel = "urgentReel";
/// <summary>
/// cutReel: true 表示分盘料,需要出到料串上
/// </summary>
public static string cutReel = "cutReel";
/// <summary>
/// smallReel: true 小料(7x8),放置到小料架上
/// </summary>
public static string smallReel = "smallReel";
/// <summary>
/// rfid: 分配的料架RFID
/// </summary>
public static string rfid = "rfid";
/// <summary>
/// rfidLoc: 料架的架位,值为 - 1时,可以自由分配皮带线, 小料时,架位为1 - 46优先走1 / 2号皮带线,47 - 92优先走3 / 4号皮带线,
/// 70,71,72时只能分配到3 / 4号皮带线; 大料时,架位1 - 6优先走1 / 2号皮带线, 7 - 12优先走3 / 4号皮带线
/// </summary>
public static string rfidLoc = "rfidLoc";
public static string barcode = "barcode";
}
}
文件属性发生变化
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Threading;
using System.Xml;
using System.Windows.Forms;
using log4net;
namespace OnlineStore.Common
{
public class ConfigAppSettings
{
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static int seq = 1;
public static int nextSeq()
{
if (seq.Equals(Int32.MaxValue))
{
LOGGER.Info("seq当前值:" + seq + ",重置seq=0");
seq = 0;
}
Interlocked.Increment(ref seq);
return seq;
}
public static string GetValue(string keyStr, string storeStr)
{
string key = keyStr + storeStr;
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
return GetValue(keyStr);
}
else
{
return config.AppSettings.Settings[key].Value;
}
}
public static decimal GetNumValue(string keyStr, string storeStr)
{
string key = keyStr + storeStr;
decimal a = 0;
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
return GetNumValue(keyStr);
}
else
{
Decimal.TryParse(config.AppSettings.Settings[key].Value, out a);
}
return a;
}
public static int GetIntValue(string keyStr, string storeStr)
{
string key = keyStr + storeStr;
int a = 0;
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
return GetIntValue(keyStr);
}
else
{
Int32.TryParse(config.AppSettings.Settings[key].Value, out a);
}
return a;
}
public static string GetValue(string key)
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
LOGGER.Error("未找到配置:" + key + ",请检查配置是否完整!");
return "";
}
else
{
return config.AppSettings.Settings[key].Value;
}
}
public static decimal GetNumValue(string key)
{
decimal a = 0;
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
LOGGER.Error("未找到配置:" + key + ",请检查配置是否完整!");
return a;
}
else
{
Decimal.TryParse(config.AppSettings.Settings[key].Value, out a);
}
return a;
}
public static int GetIntValue(string key)
{
int a = 0;
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
LOGGER.Error("未找到配置:" + key + ",请检查配置是否完整!");
return a;
}
else
{
Int32.TryParse(config.AppSettings.Settings[key].Value, out a);
}
return a;
}
public static void SaveValue(string key, int value)
{
SaveValue(key, value.ToString());
}
public static void SaveValue(string key, string value)
{
try
{
if (key.Equals("") || value.Equals(""))
{
//return;
}
//增加的内容写在appSettings段下 <add key="RegCode" value="0"/>
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] == null)
{
SetValue(key, value);
}
else
{
UpdateConfig(key, value);
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "SaveValue保存配置出错:AppKey=" + key + ",AppValue=" + value + "," + ex.StackTrace);
}
}
/// <summary>
/// 更新配置文件信息
/// </summary>
/// <param name="name">配置文件字段名称</param>
/// <param name="Xvalue">值</param>
private static void UpdateConfig(string name, string Xvalue)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(Application.ExecutablePath + ".config");
XmlNode node = doc.SelectSingleNode(@"//add[@key='" + name + "']");
XmlElement ele = (XmlElement)node;
ele.SetAttribute("value", Xvalue);
doc.Save(Application.ExecutablePath + ".config");
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "UpdateConfig保存配置出错:name=" + name + ",Xvalue=" + Xvalue + "," + ex.StackTrace);
}
}
///<summary>
///向.config文件的appKey结写入信息AppValue 保存设置
///</summary>
///<param name="AppKey">节点名</param>
///<param name="AppValue">值</param>
private static void SetValue(String AppKey, String AppValue)
{
try
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(System.Windows.Forms.Application.ExecutablePath + ".config");
XmlNode xNode;
XmlElement xElem1;
XmlElement xElem2;
xNode = xDoc.SelectSingleNode("//appSettings");
xElem1 = (XmlElement)xNode.SelectSingleNode("//add[@key='" + AppKey + "']");
if (xElem1 != null)
xElem1.SetAttribute("value", AppValue);
else
{
xElem2 = xDoc.CreateElement("add");
xElem2.SetAttribute("key", AppKey);
xElem2.SetAttribute("value", AppValue);
xNode.AppendChild(xElem2);
}
xDoc.Save(System.Windows.Forms.Application.ExecutablePath + ".config");
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "SetValue保存配置出错:AppKey=" + AppKey + ",AppValue=" + AppValue + "," + ex.StackTrace);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnlineStore.Common
{
public class FormUtil
{
public static int GetIntValue(TextBox txt)
{
int value = 0;
try
{
value = int.Parse(txt.Text);
}
catch (Exception ex)
{
value = 0;
}
return value;
}
public static short GetShortValue(TextBox txt)
{
short value = 0;
try
{
value = short.Parse(txt.Text);
}
catch (Exception ex)
{
value = 0;
}
return value;
}
public static double getDoubleValue(TextBox txt)
{
double value = 0;
try
{
value = double.Parse(txt.Text);
}
catch (Exception ex)
{
value = 0;
}
return value;
}
public static short get16ShortValue(TextBox txt)
{
short value = 0;
try
{
value = System.Convert.ToInt16(txt.Text,16);
}
catch
{
value = 0;
}
return value;
}
public static string GetShowStr(double value)
{
string wStr = "";
if (value == (int)value)
{
wStr = string.Format("{0:d}", (int)value);
}
else
{
wStr = string.Format("{0:f}", value);
}
return wStr;
}
public static string GetSpanStr(TimeSpan span)
{
//return Convert.ToDateTime(span.ToString()).ToString("HH:mm:ss");
string seconds = Math.Round(span.TotalSeconds % 60, 1).ToString();
if (seconds.IndexOf(".") >= 0)
{
seconds = seconds.ToString().PadLeft(4, '0');
}
else
{
seconds = seconds.ToString().PadLeft(2, '0');
}
return span.Hours.ToString().PadLeft(2, '0') + ":" + span.Minutes.ToString().PadLeft(2, '0') + ":" + seconds;
}
public static bool GetBoolData(Dictionary<string, string> data, string key, bool defaultValue=false)
{
if (data.ContainsKey(key))
{
try
{
return Convert.ToBoolean(data[key]);
}
catch (Exception ex)
{
}
}
return defaultValue;
}
public static int GetIntData(Dictionary<string, string> data, string key, int defaultValue = 0)
{
if (data.ContainsKey(key))
{
try
{
return Convert.ToInt32(data[key]);
}
catch (Exception ex)
{
}
}
return defaultValue;
}
}
}
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Collections;
using System.Net;
using System.Net.Security;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Reflection;
using log4net;
namespace OnlineStore.Common
{
public class HttpHelper
{
public static string Post(string url, string paramData)
{
return Post(url, paramData, Encoding.UTF8);
}
public static Operation Post(string url, Operation operation, bool simulate)
{
try
{
if (simulate)
{//模拟服务器返回
operation.status = 200;
operation.data.Clear();
operation.data.Add("posId", "A001");
string pos = "D100-111#D102-222#D104-333";
operation.data.Add("pos", pos);
if (operation.op == 1 || operation.op == 2)
{//入库或出库
string json = JsonHelper.SerializeObject(operation);
LogUtil.error( "模拟HTTP服务器返回出库入库信息:" + json);
return operation;
}
}
else
{
string json = "";
try
{
json = JsonHelper.SerializeObject(operation);
}
catch (Exception ex)
{
LogUtil.error("JsonHelper.SerializeObject(operation) 出错【operation.op=" + operation.op + "】" + ex);
}
string result = Post(url, json);
if (!string.IsNullOrEmpty(result))
{
try
{
return JsonHelper.DeserializeJsonToObject<Operation>(result);
}
catch (Exception ex)
{
LogUtil.error("JsonHelper.DeserializeJsonToObject 出错【result=" + result + "】" + ex);
}
}
}
}
catch (Exception ex)
{
LogUtil.error("Post 出错【operation.op=" + operation.op + "】:" + ex);
}
return null;
}
private static int isLog = ConfigAppSettings.GetIntValue(Setting_Init.Server_Log_Open);
public static string Post(string url, string paramData, Encoding encoding)
{
if (isLog == 1)
{
LogUtil.info("给服务器发送数据【" + paramData + "】 ");
}
if (paramData != "null" && paramData != null)
{
// LogUtil.debug( "HTTP POST to " + url + " \n\t >> " + paramData);
}
string result = "";
if (url.ToLower().IndexOf("https", System.StringComparison.Ordinal) > -1)
{
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback((sender, certificate, chain, errors) => { return true; });
}
try
{
var wc = new MyWebClient(5000);
if (string.IsNullOrEmpty(wc.Headers["Content-Type"]))
wc.Headers.Add("Content-Type", "application/json;charset=UTF-8");
wc.Encoding = encoding;
result = wc.UploadString(url, "POST", paramData);
//LogUtil.info(result);
}
catch (Exception e)
{
LogUtil.error( "POST ERROR:" + e.ToString(), 1);
}
if (!result.Contains("null") && result.Length != 0)
{
//LogUtil.debug( "receive << " + result);
}
if (isLog == 1)
{
LogUtil.info("收到服务器数据【" + result + "】");
}
return result;
}
public static string Get(string url)
{
return Get(url, Encoding.UTF8);
}
public static string Get(string url, Encoding encoding)
{
try
{
LogUtil.info( "HTTP GET FROM: " + url);
var wc = new WebClient { Encoding = encoding };
var readStream = wc.OpenRead(url);
using (var sr = new StreamReader(readStream, encoding))
{
var result = sr.ReadToEnd();
LogUtil.info( "receive << " + result);
return result;
}
}
catch (Exception e)
{
LogUtil.error( "HTTP GET ERROR:" + e.Message, 2);
}
return "";
}
}
}
\ No newline at end of file \ No newline at end of file
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace OnlineStore.Common
{
/// <summary>
/// Json帮助类
/// </summary>
public class JsonHelper
{
/// <summary>
/// 将对象序列化为JSON格式
/// </summary>
/// <param name="o">对象</param>
/// <returns>json字符串</returns>
public static string SerializeObject(object o)
{
string json = JsonConvert.SerializeObject(o);
return json;
}
/// <summary>
/// 解析JSON字符串生成对象实体
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>
/// <returns>对象实体</returns>
public static T DeserializeJsonToObject<T>(string json) where T : class
{
JsonSerializer serializer = new JsonSerializer();
StringReader sr = new StringReader(json);
object o = serializer.Deserialize(new JsonTextReader(sr), typeof(T));
T t = o as T;
return t;
}
/// <summary>
/// 解析JSON数组生成对象实体集合
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="json">json数组字符串(eg.[{"ID":"112","Name":"石子儿"}])</param>
/// <returns>对象实体集合</returns>
public static List<T> DeserializeJsonToList<T>(string json) where T : class
{
JsonSerializer serializer = new JsonSerializer();
StringReader sr = new StringReader(json);
object o = serializer.Deserialize(new JsonTextReader(sr), typeof(List<T>));
List<T> list = o as List<T>;
return list;
}
/// <summary>
/// 反序列化JSON到给定的匿名对象.
/// </summary>
/// <typeparam name="T">匿名对象类型</typeparam>
/// <param name="json">json字符串</param>
/// <param name="anonymousTypeObject">匿名对象</param>
/// <returns>匿名对象</returns>
public static T DeserializeAnonymousType<T>(string json, T anonymousTypeObject)
{
T t = JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
return t;
}
}
///// <summary>
///// 与服务器通信用对象
///// </summary>
//public class Operation
//{
// private string _cid = "";
// public string cid
// {
// get { return _cid; }
// set { _cid = value; }
// }
// public int seq { get; set; }
// public int op { get; set; }
// public int status { get; set; }
// private string _error = "";
// public string error
// {
// get { return _error; }
// set { _error = value; }
// }
// private Dictionary<string, string> _data = new Dictionary<string,string>();
// public Dictionary<string, string> data {
// get { return _data; }
// set { _data = value; }
// }
//}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using System.Reflection;
using System.Drawing;
namespace OnlineStore.Common
{
public class LogUtil
{
public static readonly ILog AIOLog = LogManager.GetLogger("AIOBOXLog");
private static LogUtil instance = new LogUtil();
public delegate void ShowLog(string msg, Color color);
public static readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static Dictionary<int, DateTime> lastErrorLogTime = new Dictionary<int, DateTime>();
public static System.Windows.Forms.RichTextBox logBox = null;
public static int showCount = 20;
public static bool debug_opened = false;
public static void info(ILog log, string msg)
{
if (log == null)
{
return;
}
log.Info(msg);
AddToBox(msg, Color.Black);
//clear();
}
public static void info(ILog log, string msg, Color color)
{
log.Info(msg);
AddToBox(msg, color);
}
public static void debug(ILog log, string msg, Color color)
{
log.Debug(msg);
if (debug_opened)
{
AddToBox(msg, color);
}
}
public static void debug(ILog log, string msg)
{
log.Debug(msg);
if (debug_opened)
{
AddToBox(msg, Color.Gray);
}
}
public static void error(string errorMsg, int type)
{
if (lastErrorLogTime.ContainsKey(type))
{
TimeSpan span = DateTime.Now - lastErrorLogTime[type];
if (span.TotalSeconds > 10)
{
lastErrorLogTime.Remove(type);
lastErrorLogTime.Add(type, DateTime.Now);
error(LOGGER, errorMsg);
}
}
else
{
lastErrorLogTime.Add(type, DateTime.Now);
error(LOGGER, errorMsg);
}
}
public static void error(ILog log, string errorMsg, Exception ex = null)
{
if (errorMsg.Trim().Equals(""))
{
return;
}
if (ex == null)
{
log.Error(errorMsg);
}
else
{
log.Error(errorMsg, ex);
}
AddToBox(errorMsg, Color.Red);
}
private static void AddToBox(string msg, Color color)
{
try
{
ShowLogPro(msg, color);
}
catch (Exception ex)
{
LOGGER.Error("出错:", ex);
}
}
private static List<string> logList = new List<string>();
public static string LastText = "";
private static void ShowLogPro(string msg, Color color)
{
try
{
if (logList.Count > 0)
{
// logList.RemoveAt(0);
}
if (logList.Count >= showCount)
{
logList.RemoveAt(0);
}
string text = "";
foreach (string str in logList)
{
text += str;
}
System.DateTime now = System.DateTime.Now;
logList.Add(now.ToLongTimeString() + " " + msg + Environment.NewLine);
if (logBox == null)
{
return;
}
LastText = text;
if (logBox.Visible)
{
logBox.Text = text;
// logBox.Focus(); //使文本框获取焦点
logBox.AppendText(now.ToLongTimeString() + " " + msg + Environment.NewLine); //增加文本
TimeSpan span = DateTime.Now - lastTime;
if (span.TotalSeconds > 3000000)
{
lastTime = DateTime.Now;
logBox.Select(logBox.Text.Length, 0); //设置光标的位置到文本尾
logBox.ScrollToCaret(); //滚动到控件光标处
}
}
}
catch (Exception ex)
{
LOGGER.Error("出错:" + ex.ToString());
}
}
private static DateTime lastTime = DateTime.Now;
public static void UpdateLogbox()
{
if (logBox != null && logBox.Visible)
{
logBox.Text = LastText;
TimeSpan span = DateTime.Now - lastTime;
if (span.TotalSeconds > 3000000)
{
lastTime = DateTime.Now;
logBox.Select(logBox.Text.Length, 0); //设置光标的位置到文本尾
logBox.ScrollToCaret(); //滚动到控件光标处
}
}
}
public static void ClearLog()
{
if (logBox != null)
{
LastText = "";
logList.Clear();
logBox.Text = "";
}
}
public static void debug(string msg)
{
debug(LOGGER, msg);
}
public static void error(string errorMsg, Exception ex = null)
{
error(LOGGER, errorMsg, ex);
}
public static void info(string msg)
{
info(LOGGER, msg);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
namespace OnlineStore.Common
{
public class MyWebClient:WebClient
{
private int _timeout;
/// <summary>
/// 超时时间(毫秒)
/// </summary>
public int Timeout
{
get
{
return _timeout;
}
set
{
_timeout = value;
}
}
public MyWebClient()
{
this._timeout = 60000;
}
public MyWebClient(int timeout)
{
this._timeout = timeout;
}
protected override WebRequest GetWebRequest(Uri address)
{
var result = base.GetWebRequest(address);
result.Timeout = this._timeout;
return result;
}
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace OnlineStore.Common
{
/// <summary>
/// 扫码枪连接类
/// </summary>
public class ScanSocket
{
private readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event ScanRevice OnScanRevice;
public delegate void ScanRevice(string message);
/// <summary>
/// 扫码枪链接
/// </summary>
private TcpClient scannerSocket;
/// <summary>
/// 扫描枪 是否开始运行
/// </summary>
public bool isScannerRun = false;
/// <summary>
/// 连接扫码枪
/// </summary>
/// <param name="serverIp">扫码枪Ip</param>
/// <param name="port">扫码枪端口号</param>
/// <returns>是否连接成功</returns>
public bool ConnectScanner(string serverIp, int port)
{
return StartScanner(serverIp, port, false);
}
/// <summary>
/// 停止扫码枪
/// </summary>
public void StopScanner()
{
try
{
scannerSocket.close();
isScannerRun = false;
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错:" + ex);
}
}
/// <summary>
/// 发送扫码命令开始扫码
/// </summary>
public void BeginScannering()
{
string str = ConfigAppSettings.GetValue(Setting_Init.scanner_start_command);
if (str.Equals(""))
{
str = "S";
}
scannerSocket.send(str);
//onCodeReceived("AAAA");
}
/// <summary>
/// 开启扫码枪
/// </summary>
private bool StartScanner(string serverIp, int port, bool isMustCon)
{
bool result = true;
try
{
if (!isScannerRun || isMustCon)
{
if (scannerSocket == null)
{
scannerSocket = new TcpClient();
}
result = scannerSocket.connect(serverIp, port, new TcpClient.HandleMessage(onCodeReceived));
if (result)
{
isScannerRun = true;
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错:" + ex);
}
return result;
}
/// <summary>
/// 扫码枪数据接收
/// </summary>
/// <param name="message"></param>
private void onCodeReceived(string message)
{
try
{
message = ScanCodeManager.ReplaceCode(message);
if (OnScanRevice != null)
{
OnScanRevice.Invoke(message);
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错:" + ex.ToString());
}
}
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
namespace OnlineStore.Common
{
public class SerialBean
{
#region 全部变量
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private SerialPort _serialPort = null;
//定义委托
public delegate void SerialPortDataReceiveEventArgs(string portName, object sender, SerialDataReceivedEventArgs e, byte[] bits);
//定义接收数据事件
public event SerialPortDataReceiveEventArgs DataReceived;
//定义接收错误事件
//public event SerialErrorReceivedEventHandler Error;
//接收事件是否有效 false表示有效
public bool ReceiveEventFlag = false;
#endregion
#region 获取串口名
private string protName;
public string PortName
{
get { return _serialPort.PortName; }
set
{
_serialPort.PortName = value;
protName = value;
}
}
#endregion
#region 获取比特率
private int baudRate;
public int BaudRate
{
get { return _serialPort.BaudRate; }
set
{
_serialPort.BaudRate = value;
baudRate = value;
}
}
#endregion
#region 默认构造函数
///// <summary>
///// 默认构造函数,操作COM1,速度为9600,没有奇偶校验,8位字节,停止位为1 "COM1", 9600, Parity.None, 8, StopBits.One
///// </summary>
//public SerialBean()
//{
// _serialPort = new SerialPort();
//}
#endregion
#region 构造函数
///// <summary>
///// 构造函数,
///// </summary>
///// <param name="comPortName"></param>
//public SerialBean(string comPortName)
//{
// _serialPort = new SerialPort(comPortName);
// _serialPort.BaudRate = 9600;
// _serialPort.Parity = Parity.Even;
// _serialPort.DataBits = 8;
// _serialPort.StopBits = StopBits.One;
// _serialPort.Handshake = Handshake.None;
// _serialPort.RtsEnable = true;
// _serialPort.ReadTimeout = 2000;
// setSerialPort();
//}
#endregion
#region 构造函数,可以自定义串口的初始化参数
/// <summary>
/// 构造函数,可以自定义串口的初始化参数
/// </summary>
/// <param name="comPortName">需要操作的COM口名称</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="parity">奇偶校验位</param>
/// <param name="dataBits">数据长度</param>
/// <param name="stopBits">停止位</param>
public SerialBean(string comPortName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_serialPort = new SerialPort(comPortName, baudRate, parity, dataBits, stopBits);
_serialPort.RtsEnable = true; //自动请求
_serialPort.ReadTimeout = 3000;//超时
setSerialPort();
}
#endregion
#region 析构函数
/// <summary>
/// 析构函数,关闭串口
/// </summary>
~SerialBean()
{
if (_serialPort.IsOpen)
_serialPort.Close();
}
#endregion
#region 设置串口参数
/// <summary>
/// 设置串口参数
/// </summary>
/// <param name="comPortName">需要操作的COM口名称</param>
/// <param name="baudRate">COM的速度</param>
/// <param name="dataBits">数据长度</param>
/// <param name="stopBits">停止位</param>
public void setSerialPort(string comPortName, int baudRate, int dataBits, int stopBits)
{
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.PortName = comPortName;
_serialPort.BaudRate = baudRate;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = dataBits;
_serialPort.StopBits = (StopBits)stopBits;
_serialPort.Handshake = Handshake.None;
_serialPort.RtsEnable = false;
_serialPort.ReadTimeout = 3000;
_serialPort.NewLine = "/r/n";
setSerialPort();
}
#endregion
#region 设置接收函数
/// <summary>
/// 设置串口资源,还需重载多个设置串口的函数
/// </summary>
void setSerialPort()
{
if (_serialPort != null)
{
//设置触发DataReceived事件的字节数为1
_serialPort.ReceivedBytesThreshold = 1;
//接收到一个字节时,也会触发DataReceived事件
_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
//接收数据出错,触发事件
_serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);
//打开串口
//openPort();
}
}
#endregion
#region 打开串口资源
/// <summary>
/// 打开串口资源
/// <returns>返回bool类型</returns>
/// </summary>
public bool openPort()
{
bool ok = false;
//如果串口是打开的,先关闭
if (_serialPort.IsOpen)
_serialPort.Close();
try
{
//打开串口
_serialPort.Open();
ok = true;
}
catch (Exception Ex)
{
LogUtil.error(LOGGER, Ex.ToString());
//throw Ex;
}
return ok;
}
#endregion
#region 关闭串口
/// <summary>
/// 关闭串口资源,操作完成后,一定要关闭串口
/// </summary>
public void closePort()
{
//如果串口处于打开状态,则关闭
if (_serialPort.IsOpen)
_serialPort.Close();
}
public void clearInBuffer()
{
if (_serialPort.IsOpen)
{
_serialPort.DiscardInBuffer();
}
}
public void clearOutBuffer()
{
if (_serialPort.IsOpen)
{
_serialPort.DiscardOutBuffer();
}
}
#endregion
#region 接收串口数据事件
private object LockReviceObj = "";
/// <summary>
/// 接收串口数据事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
lock (LockReviceObj)
{
//禁止接收事件时直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
System.Threading.Thread.Sleep(20);
byte[] _data = new byte[_serialPort.BytesToRead];
_serialPort.Read(_data, 0, _data.Length);
if (_data.Length == 0) { return; }
if (DataReceived != null)
{
DataReceived(_serialPort.PortName, sender, e, _data);
}
_serialPort.DiscardInBuffer(); //清空接收缓冲区
}
catch (Exception ex)
{
LogUtil.error(LOGGER, ex.ToString());
}
}
}
#endregion
#region 接收数据出错事件
/// <summary>
/// 接收数据出错事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
}
#endregion
/// <summary>
/// 发送命令
/// </summary>
/// <param name="SendData">发送数据</param>
/// <param name="ReceiveData">接收数据</param>
/// <param name="Overtime">超时时间</param>
/// <param name="ReceiveLength">接收数据长度</param>
/// <returns></returns>
public int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime, int ReceiveLength)
{
if (_serialPort.IsOpen)
{
try
{
lock (LockReviceObj)
{
ReceiveEventFlag = true; //关闭接收事件
_serialPort.DiscardInBuffer(); //清空接收缓冲区
_serialPort.Write(SendData, 0, SendData.Length);
int num = 0, ret = 0;
System.Threading.Thread.Sleep(10);
ReceiveEventFlag = false; //打开事件
if (ReceiveData == null)
{
ReceiveData = new byte[ReceiveLength];
}
while (num++ < Overtime)
{
if (_serialPort.BytesToRead >= ReceiveData.Length)
break;
System.Threading.Thread.Sleep(10);
}
if (_serialPort.BytesToRead >= ReceiveData.Length)
{
ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);
}
else
{
ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);
}
ReceiveEventFlag = false; //打开事件
return ret;
}
}
catch (Exception ex)
{
ReceiveEventFlag = false;
throw ex;
}
}
return -1;
}
#region 发送数据string类型
public void SendData(string data)
{ //发送数据
//禁止接收事件时直接退出
if (ReceiveEventFlag)
{
return;
}
if (_serialPort.IsOpen)
{
_serialPort.Write(data);
}
}
#endregion
#region 发送数据byte类型
/// <summary>
/// 数据发送
/// </summary>
/// <param name="data">要发送的数据字节</param>
public void SendData(byte[] data, int offset, int count)
{
string strSend = "";
for (int i = 0; i < data.Length; i++)
{
strSend += string.Format("{0:X2} ", data[i]);
}
LOGGER.Debug("【" + _serialPort.PortName + "】发送数据【" + strSend + "】");
//禁止接收事件时直接退出
if (ReceiveEventFlag)
{
return;
}
try
{
if (_serialPort.IsOpen)
{
//_serialPort.DiscardInBuffer();//清空接收缓冲区
_serialPort.Write(data, offset, count);
}
}
catch (Exception ex)
{
_serialPort.DiscardOutBuffer();
throw ex;
}
}
#endregion
#region 发送命令
/// <summary>
/// 发送命令
/// </summary>
/// <param name="SendData">发送数据</param>
/// <param name="ReceiveData">接收数据</param>
/// <param name="Overtime">超时时间</param>
/// <returns></returns>
public int SendCommand(byte[] SendData, ref byte[] ReceiveData, int Overtime)
{
if (_serialPort.IsOpen)
{
try
{
ReceiveEventFlag = true; //关闭接收事件
_serialPort.DiscardInBuffer(); //清空接收缓冲区
_serialPort.Write(SendData, 0, SendData.Length);
int num = 0, ret = 0;
System.Threading.Thread.Sleep(10);
ReceiveEventFlag = false; //打开事件
while (num++ < Overtime)
{
if (_serialPort.BytesToRead >= ReceiveData.Length)
break;
System.Threading.Thread.Sleep(10);
}
if (_serialPort.BytesToRead >= ReceiveData.Length)
{
ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);
}
else
{
ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);
}
ReceiveEventFlag = false; //打开事件
return ret;
}
catch (Exception ex)
{
ReceiveEventFlag = false;
throw ex;
}
}
return -1;
}
#endregion
#region 获取串口
/// <summary>
/// 获取所有已连接短信猫设备的串口
/// </summary>
/// <returns></returns>
public string[] serialsIsConnected()
{
List<string> lists = new List<string>();
string[] seriallist = getSerials();
foreach (string s in seriallist)
{
}
return lists.ToArray();
}
#endregion
#region 获取当前全部串口资源
/// <summary>
/// 获得当前电脑上的所有串口资源
/// </summary>
/// <returns></returns>
public string[] getSerials()
{
return SerialPort.GetPortNames();
}
#endregion
#region 字节型转换16
/// <summary>
/// 把字节型转换成十六进制字符串
/// </summary>
/// <param name="InBytes"></param>
/// <returns></returns>
public static string ByteToString(byte[] InBytes)
{
string StringOut = "";
foreach (byte InByte in InBytes)
{
StringOut = StringOut + String.Format("{0:X2} ", InByte);
}
return StringOut;
}
#endregion
#region 十六进制字符串转字节型
/// <summary>
/// 打包方法,可以将十六制字符串转成byte[] ,字符串没有空格
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
//public static byte[] StringToByte(string s)
//{
// string temps = ReplaceSpace(s);
// if (temps.Length % 2 != 0)
// {
// temps = "0" + temps;
// }
// byte[] tempb = new byte[50];
// int j = 0;
// for (int i = 0; i < temps.Length; i = i + 2, j++)
// {
// tempb[j] = Convert.ToByte(temps.Substring(i, 2), 16);
// }
// byte[] send = new byte[j];
// Array.Copy(tempb, send, j);
// return send;
//}
//除去空格
public static string ReplaceSpace(string str)
{
string putout = "";
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{ putout += str[i]; }
}
return putout;
}
#endregion
#region 字节型转十六进制字符串
/// <summary>
/// 字节数组转16进制字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string byteToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
#endregion
#region 计算校验码
public static void CalculateBCC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
{
byte check = 0;
check = (byte)(pByte[0] ^ (pByte[1]));
for (int i = 2; i < pByte.Length; i++)
{
check = (byte)(check ^ (pByte[i]));
}
pChecksum = check;
}
//public static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
//{
// int nBit;
// ushort nShiftedBit;
// pChecksum = 0xFFFF;
// for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
// {
// pChecksum ^= pByte[nByte];
// for (nBit = 0; nBit < 8; nBit++)
// {
// if ((pChecksum & 0x1) == 1)
// {
// nShiftedBit = 1;
// }
// else
// {
// nShiftedBit = 0;
// }
// pChecksum >>= 1;
// if (nShiftedBit != 0)
// {
// pChecksum ^= 0xA001;
// }
// }
// }
//}
#endregion
}
}
文件属性发生变化
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{513BC1C9-800D-43A6-9499-3700BAEC3554}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OnlineStore.DeviceLibrary</RootNamespace>
<AssemblyName>DeviceLibrary</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>AnyCPU</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Asa.IOModule.AIOBOX">
<HintPath>..\..\dll\Asa.IOModule.AIOBOX.dll</HintPath>
</Reference>
<Reference Include="Asa.RFID">
<HintPath>..\..\dll\Asa.RFID.dll</HintPath>
</Reference>
<Reference Include="AsaPL.AgvClient">
<HintPath>..\..\dll\AsaPL.AgvClient.dll</HintPath>
</Reference>
<Reference Include="HFReader9CSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\dll\RFID\HFReader9CSharp.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\dll\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="acLine\LineBean.cs" />
<Compile Include="acLine\LineBean_Partial.cs" />
<Compile Include="acLine\LineManager.cs" />
<Compile Include="acLine\WaitUtil.cs" />
<Compile Include="agvClient\AgvClient_Line.cs" />
<Compile Include="bean\StoreMoveInfo.cs" />
<Compile Include="IO\AIOBOX\AIOBOXManager.cs" />
<Compile Include="IO\IOManager.cs" />
<Compile Include="IO\KangNaiDe\KNDManager.cs" />
<Compile Include="IO\KangNaiDe\MasterTcpClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="bean\StoreStep.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="RFIDManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj">
<Project>{43cdd09e-fcf3-4960-a01d-3bbfe9933122}</Project>
<Name>Common</Name>
</ProjectReference>
<ProjectReference Include="..\LoadCVSLibrary\LoadCSVLibrary.csproj">
<Project>{064bebf5-8faa-4ea2-a5f3-a06e6e7d9251}</Project>
<Name>LoadCSVLibrary</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="LineConfig\LineConfig.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file \ No newline at end of file
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System.Threading.Tasks;
using Asa.IOModule;
using System.Windows.Forms;
namespace OnlineStore.DeviceLibrary
{
public class AIOBOXManager : IOManager
{
//public static uint DefaultDICount = 16;
//public static uint DefaultDOCount = 16;
public readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public Dictionary<string, AIOBOX> AIOMap = new Dictionary<string, AIOBOX>();
public Dictionary<string, List<Box_Sta>> DIValueMap = new Dictionary<string, List<Box_Sta>>();
public Dictionary<string, List<Box_Sta>> DOValueMap = new Dictionary<string, List<Box_Sta>>();
private object DIMapLock = "";
private object DOMapLock = "";
private object DILock = "";
private object DOLock = "";
public override void ConnectionIOList(List<string> DIONameList)
{
foreach (string ip in DIONameList)
{
ConnectionIP(ip);
}
}
private bool isProcess = false;
private DateTime lastTime = DateTime.Now;
public void ConnectionIP(string ioIp)
{
AIOBOX aioBox = null;
if (AIOMap.ContainsKey(ioIp))
{
aioBox = AIOMap[ioIp];
try
{
if (null != aioBox)
{
aioBox.Close();
aioBox = null;
}
}
catch (Exception ex)
{
LogUtil.error("关闭Io模块【" + ioIp + "】出错:", ex);
}
AIOMap.Remove(ioIp);
}
if (DIValueMap.ContainsKey(ioIp))
{
DIValueMap.Remove(ioIp);
}
if (DOValueMap.ContainsKey(ioIp))
{
DOValueMap.Remove(ioIp);
}
int DIMS = ConfigAppSettings.GetIntValue("DIMS");
if (DIMS < 20)
{
DIMS = 20;
}
int DOMS = ConfigAppSettings.GetIntValue("DOMS");
if (DOMS < 200)
{
DOMS = 200;
}
int DILength = LineManager.Config.GetDILength(ioIp);
int DOLength = LineManager.Config.GetDOLength(ioIp);
string logName = "IO模块[" + ioIp + "] DI[" + DILength + "] DO[" + DOLength + "],[" + DIMS + "] [" + DOMS + "]";
try
{
aioBox = new AIOBOX();
aioBox.LogPath(Application.StartupPath + @"\logs\aio\", LogType.OnlyError);
aioBox.IP = ioIp;
aioBox.SetInput(Asa.IOModule.Box_Type.DI, DILength);
aioBox.SetOutput(Asa.IOModule.Box_Type.DO, DOLength);
//DI主动上传
aioBox.AutoReadInput(true);
aioBox.AutoReadOutput(false, DOMS);
aioBox.DI_Changed_Event += AioBox_DI_Changed_Event; ;
aioBox.DO_Changed_Event += AioBox_DO_Changed_Event;
LogUtil.info("开始连接:" + logName + ":" + aioBox.ErrInfo);
aioBox.Connect();
AIOMap.Add(ioIp, aioBox);
Thread.Sleep(5);
//读取所有的DO
ReadAllDI(ioIp, 0);
Thread.Sleep(5);
GC.Collect();
}
catch (Exception error)
{
LogUtil.error(LOGGER, "连接IO模块 " + logName + " 出错:" + error.ToString());
}
}
private DateTime lastLogTime = DateTime.Now;
private void AioBox_Log_Out_Event(AIOBOX box, string[] s)
{
foreach (string str in s)
{
LogUtil.AIOLog.Debug("[" + box.IP + "]" + str);
}
}
private void AioBox_DI_Changed_Event(AIOBOX box, Box_Sta[] sta)
{
try
{
UpdateAllDI(box.IP, sta);
}
catch (Exception ex)
{
LogUtil.error("AioBox_DI_Changed_Event出错:", ex);
}
}
private void AioBox_DO_Changed_Event(AIOBOX box, Box_Sta[] sta)
{
try
{
UpdateAllDO(box.IP, sta);
}
catch (Exception ex)
{
LogUtil.error("AioBox_DO_Changed_Event出错:", ex);
}
}
private void UpdateAllDI(string ip, Box_Sta[] sta)
{
if (sta != null && sta.Length >= LineManager.Config.GetDILength(ip))
{
string updateDi = "[" + ip + "]:";
bool needUpdate = false;
List<Box_Sta> newList = new List<Box_Sta>();
newList.AddRange(sta);
List<Box_Sta> oldList = null;
DIValueMap.TryGetValue(ip, out oldList);
if (oldList == null || oldList.Count.Equals(newList.Count).Equals(false))
{
needUpdate = true;
}
else
{
for (int i = 0; i < newList.Count; i++)
{
if (!(oldList[i].Equals(newList[i])))
{
needUpdate = true;
break;
}
}
}
if (needUpdate)
{
lock (DILock)
{
if (DIValueMap.ContainsKey(ip))
{
DIValueMap.Remove(ip);
}
DIValueMap.Add(ip, newList);
}
}
}
}
private void UpdateAllDO(string ip, Box_Sta[] sta)
{
if (sta != null && sta.Length >= LineManager.Config.GetDOLength(ip))
{
bool needUpdate = false;
List<Box_Sta> newList = new List<Box_Sta>();
newList.AddRange(sta);
List<Box_Sta> oldList = null;
DOValueMap.TryGetValue(ip, out oldList);
if (oldList == null || oldList.Count.Equals(newList.Count).Equals(false))
{
needUpdate = true;
}
else
{
for (int i = 0; i < newList.Count; i++)
{
if (!(oldList[i].Equals(newList[i])))
{
needUpdate = true;
break;
}
}
}
if (needUpdate)
{
lock (DOLock)
{
if (DOValueMap.ContainsKey(ip))
{
DOValueMap.Remove(ip);
}
DOValueMap.Add(ip, newList);
}
}
}
}
//关闭所有的DO
public override void CloseAllDO()
{
foreach (AIOBOX aio in AIOMap.Values)
{
ushort length = LineManager.Config.GetDOLength(aio.IP);
for (ushort i = 0; i < length; i++)
{
aio.WriteDO(i, Box_Sta.Off);
}
}
}
public override void CloseAllConnection()
{
foreach (AIOBOX aio in AIOMap.Values)
{
try
{
aio.Close();
}
catch (Exception ex)
{
LogUtil.error("aio.Close出错:", ex);
}
}
AIOMap.Clear();
}
public override void WriteSingleDO(string ioIp, byte slaveId, ushort StartAddress, IO_VALUE onOff)
{
try
{
AIOBOX aioBox = getAIO(ioIp);
if (aioBox != null)
{
bool result = aioBox.WriteDO(StartAddress, GetBox_Sta(onOff));
if (!result)
{
LogUtil.error("AIO WriteSingleDO [" + ioIp + "] [" + StartAddress + "] 失败:" + aioBox.ErrInfo);
}
}
else
{
LogUtil.error(LOGGER, "WriteSingleDO出错 没有连接IO模块:" + ioIp);
}
}
catch (Exception ex)
{
LOGGER.Error("AIO WriteSingleDO [" + ioIp + "] [" + StartAddress + "] 出错啦:", ex);
}
}
public override void WriteSingleDO(string ioIp, byte slaveId, ushort StartAddress, IO_VALUE onOff, int mSeconds)
{
try
{
AIOBOX aioBox = getAIO(ioIp);
if (aioBox != null)
{
Box_Sta currBox_Sta = GetBox_Sta(onOff);
aioBox.WriteDO(StartAddress, currBox_Sta);
//写入之后,等待指定间隔后回写
System.Timers.Timer mytimer = new System.Timers.Timer(mSeconds);
mytimer.Elapsed += (o1, e1) =>
{
try
{
aioBox.WriteDO(StartAddress, aioBox.ReverseStatus(currBox_Sta));
LogUtil.debug(LOGGER, "**********定时回写入 IO [" + ioIp + "] [" + StartAddress + "]值" + aioBox.ReverseStatus(currBox_Sta) + "】:");
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "**********定时回写入 出错:", ex);
}
};
mytimer.AutoReset = false;//设置是否自动重启,即自动执行多次;
mytimer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件mytask;
}
else
{
LogUtil.error(LOGGER, "AIO WriteSingleDO [" + ioIp + "] [" + StartAddress + "] 出错 没有连接IO模块:" + ioIp);
}
}
catch (Exception ex)
{
LogUtil.error("AIO WriteSingleDO [" + ioIp + "] [" + StartAddress + "] 出错:" + ioIp);
}
}
public override void ReadAllDI(string ioIp, byte slaveId)
{
try
{
AIOBOX aioBox = getAIO(ioIp);
if (aioBox != null)
{
Box_Sta[] allDi = aioBox.ReadDI(0, LineManager.Config.GetDILength(ioIp));
UpdateAllDI(ioIp, allDi);
}
}
catch (Exception ex)
{
LogUtil.error("ReadAllDI [" + ioIp + "]出错:" + ioIp);
}
}
public override void ReadAllDO(string ioIp, byte slaveId)
{
try
{
AIOBOX aioBox = getAIO(ioIp);
if (aioBox != null)
{
// int startIndex = StoreManager.Config.GetDILength(ioIp);
Box_Sta[] allDO = aioBox.ReadDO(0, LineManager.Config.GetDOLength(ioIp));
UpdateAllDO(ioIp, allDO);
}
}
catch (Exception ex)
{
LogUtil.error("ReadAllDO [" + ioIp + "]出错:" + ioIp);
}
}
public override IO_VALUE GetDOValue(string ioIP, byte slaveId, ushort StartAddress)
{
IO_VALUE value = IO_VALUE.LOW;
try
{
AIOBOX aioBox = getAIO(ioIP);
if (aioBox != null)
{
Box_Sta sta = Box_Sta.Off;
if (DOValueMap.ContainsKey(ioIP) && DOValueMap[ioIP].Count > StartAddress)
{
sta = DOValueMap[ioIP][StartAddress];
}
else
{ sta = aioBox.ReadDO(StartAddress); }
if (sta.Equals(Box_Sta.On))
{
value = IO_VALUE.HIGH;
}
else
{
value = IO_VALUE.LOW;
}
}
}
catch (Exception ex)
{
LogUtil.error("GetDOValue [" + ioIP + "] [" + StartAddress + "] 出错:", ex);
}
return value;
}
public override IO_VALUE GetDIValue(string ioIP, byte slaveId, ushort StartAddress)
{
IO_VALUE value = IO_VALUE.LOW;
for (int i = 1; i <= 3; i++)
{
try
{
AIOBOX aioBox = getAIO(ioIP);
if (aioBox != null)
{
Box_Sta sta = Box_Sta.Off;
// Box_Addr addr = GetAddr(StartAddress);
int index = StartAddress;
if (DIValueMap.ContainsKey(ioIP) && DIValueMap[ioIP].Count > index)
{
sta = DIValueMap[ioIP][index];
}
else
{
sta = aioBox.ReadDI(StartAddress);
}
if (sta.Equals(Box_Sta.On))
{
value = IO_VALUE.HIGH;
}
else
{
value = IO_VALUE.LOW;
}
}
break;
}
catch (Exception ex)
{
LogUtil.error(" 第【" + i + "】次 GetDIValue [" + ioIP + "] [" + StartAddress + "] 出错:", ex);
}
}
return value;
}
public override IO_VALUE GetIOValue(ConfigIO configIO)
{
IO_VALUE value = IO_VALUE.LOW;
try
{
if (configIO.ProType.Equals(ConfigItemType.DI))
{
return GetDIValue(configIO.IO_IP, configIO.SlaveID, configIO.GetIOAddr());
}
else if (configIO.ProType.Equals(ConfigItemType.DO))
{
return GetDOValue(configIO.IO_IP, configIO.SlaveID, configIO.GetIOAddr());
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, " GetIOValue [" + configIO.IO_IP + "] [" + configIO.GetIOAddr() + "] 获取数据出错:", ex);
}
return value;
}
private Box_Sta GetBox_Sta(IO_VALUE onOff)
{
if (onOff.Equals(IO_VALUE.HIGH))
{
return Box_Sta.On;
}
else
{
return Box_Sta.Off;
}
}
private AIOBOX getAIO(string ioIp)
{
AIOBOX aioBox = null;
if (AIOMap.ContainsKey(ioIp))
{
aioBox = AIOMap[ioIp];
}
return aioBox;
}
//public override bool IsConnect(string ip)
//{
// if (AIOMap.ContainsKey(ip))
// {
// if (AIOMap[ip].IsConn)
// {
// return true;
// }
// return false;
// }
// return false;
//}
}
}
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace OnlineStore.DeviceLibrary
{
public abstract class IOManager
{
public static IOManager instance = null;
public abstract void ConnectionIOList(List<string> dIODeviceNameList);
#region KNDIO
public static void IOMove(string ioType, IO_VALUE ioValue)
{
if (LineManager.Config.StoreDOList.ContainsKey(ioType))
{
ConfigIO configIo = LineManager.Config.StoreDOList[ioType];
instance.WriteSingleDO(configIo.IO_IP, configIo.SlaveID, configIo.GetIOAddr(), ioValue);
Thread.Sleep(60);
}
else
{
LogUtil.error("没有DO=" + ioType);
}
}
public static void CIOMove(string ioType,IO_VALUE ioValue)
{
if (!IOValue(ioType).Equals(ioValue))
{
IOMove(ioType, ioValue);
}
}
public static IO_VALUE IOValue(string ioType)
{
IO_VALUE ioValue = IO_VALUE.LOW;
if (LineManager.Config.StoreDIList.ContainsKey(ioType))
{
ConfigIO configIo = LineManager.Config.StoreDIList[ioType];
ioValue = instance.GetDIValue(configIo.IO_IP, configIo.SlaveID, configIo.GetIOAddr());
//UpdateDoValue(ioType, ioValue);
}
else if (LineManager.Config.StoreDOList.ContainsKey(ioType))
{
ConfigIO configIo = LineManager.Config.StoreDOList[ioType];
ioValue = instance.GetDOValue(configIo.IO_IP, configIo.SlaveID, configIo.GetIOAddr());
}
else
{
LogUtil.error("没有DO=" + ioType);
}
return ioValue;
}
public static IO_VALUE DOValue(string ioType)
{
IO_VALUE ioValue = IO_VALUE.LOW;
if (LineManager.Config.StoreDOList.ContainsKey(ioType))
{
ConfigIO configIo = LineManager.Config.StoreDOList[ioType];
ioValue = instance.GetDOValue(configIo.IO_IP, configIo.SlaveID, configIo.GetIOAddr());
}
else
{
LogUtil.error("没有DO=" + ioType);
}
return ioValue;
}
#endregion
public static void Init()
{
bool isAIOBox = ConfigAppSettings.GetIntValue(Setting_Init.UseAIOBOX).Equals(1);
if (isAIOBox)
{
instance = new AIOBOXManager();
}
else
{
instance = new KNDManager();
}
}
public abstract void ReadAllDI(string deviceName, byte slaveId);
public abstract void ReadAllDO(string deviceName, byte slaveId);
public abstract void WriteSingleDO(string deviceName, byte slaveId, ushort index, IO_VALUE value, int time);
public abstract void WriteSingleDO(string deviceName, byte slaveId, ushort index, IO_VALUE value);
public abstract IO_VALUE GetDIValue(string deviceName, byte slaveID, ushort v);
public abstract IO_VALUE GetDOValue(string deviceName, byte slaveID, ushort v);
public abstract IO_VALUE GetIOValue(ConfigIO configIO);
public abstract void CloseAllDO();
public abstract void CloseAllConnection();
}
}
using log4net;
using OnlineStore.Common;
//using OnlineStore.DeviceLibrary.doubleStore;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
namespace OnlineStore.DeviceLibrary
{
/// <summary>
/// 康奈德IO控制模块
/// </summary>
public class KNDManager : IOManager
{
public static ushort DIStartAddress = 200;
public static ushort DoStartAddress = 100;
//public static ushort DefaultDILength = 16;
//public static ushort DefaultDOLength = 16;
private static byte DefualtSlaveID = 255;
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static Dictionary<string, MasterTcpClient> mastMap = new Dictionary<string, MasterTcpClient>();
public static Dictionary<string, List<KNDIO>> DIValueMap = new Dictionary<string, List<KNDIO>>();
public static Dictionary<string, List<KNDIO>> DOValueMap = new Dictionary<string, List<KNDIO>>();
private static object DIMapLock = "";
private static object DOMapLock = "";
public static System.Timers.Timer timer = null;
private static ushort port = 502;
public static void ConnectionIP(string ioIp)
{
if (timer == null)
{
timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.AutoReset = true;
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
}
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
if (null != MBmaster)
{
MBmaster.disconnect();
MBmaster.Dispose();
MBmaster = null;
lock (DIMapLock)
{
if (DIValueMap.ContainsKey(ioIp))
{
DIValueMap.Remove(ioIp);
}
}
lock (DOMapLock)
{
if (DOValueMap.ContainsKey(ioIp))
{
DOValueMap.Remove(ioIp);
}
}
}
mastMap.Remove(ioIp);
}
try
{
// Create new modbus master and add event functions
MBmaster = new MasterTcpClient(ioIp, port);
MBmaster.OnResponseData += new MasterTcpClient.ResponseData(MBmaster_OnResponseData);
MBmaster.OnException += new MasterTcpClient.ExceptionData(MBmaster_OnException);
MBmaster.autoConnectOfBreak = false;
mastMap.Add(ioIp, MBmaster);
Thread.Sleep(10);
//读取所有的DO
ReadMultipleDO(ioIp, DefualtSlaveID, DoStartAddress, LineManager.Config.GetDOLength(ioIp));
}
catch (Exception error)
{
LogUtil.error(LOGGER, "连接IO模块[" + ioIp + "]出错:" + error.ToString());
}
}
public override void ReadAllDI(string ioIp, byte slaveId)
{
ReadMultipleDI(ioIp, (byte)slaveId, (ushort)DIStartAddress, 16);
}
public override void ReadAllDO(string ioIp, byte slaveId)
{
ReadMultipleDO(ioIp, (byte)slaveId, (ushort)DoStartAddress, 16);
}
/// <summary>
/// 判断Io模块是否连接
/// </summary>
public static bool IsConnection(string ip)
{
try
{
List<string> list = new List<string>(mastMap.Keys);
foreach (string io in list)
{
if (io.Equals(ip))
{
//判断是否连接,如果没有连接自动重连
MasterTcpClient clinet = mastMap[io];
if (clinet.ISConnection())
{
return true;
}
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错啦:" + ex.ToString());
}
return false;
}
private static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
List<string> list = new List<string>(mastMap.Keys);
foreach (string io in list)
{
//判断是否连接,如果没有连接自动重连
MasterTcpClient clinet = mastMap[io];
if (clinet.ISConnection())
{
//ReadMultipleDI(io, DefualtSlaveID, DIStartAddress, DefualtLength);
}
else
{
ConnectionIP(io);
LogUtil.error(LOGGER, io + "当前没有连上,重连" + io);
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错啦:" + ex.ToString());
}
Thread.Sleep(1);
}
public override void ConnectionIOList(List<string> DIONameList)
{
foreach (string ip in DIONameList)
{
ConnectionIP(ip);
}
}
public static void ReadMultipleDI(string ioIp, byte slaveId, ushort StartAddress, ushort length)
{
ushort ID = 2;
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
MBmaster.ReadDiscreteInputs(ID, StartAddress, length, slaveId);
}
else
{
LogUtil.error(LOGGER, "ReadMultipleDI出错 没有连接IO模块:" + ioIp);
}
}
public static void ReadMultipleDO(string ioIp, byte slaveId, ushort StartAddress, ushort length)
{
ushort ID = 1;
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
MBmaster.ReadCoils(ID, StartAddress, length, slaveId);
}
else
{
LogUtil.error(LOGGER, "ReadMultipleDO出错 没有连接IO模块:" + ioIp);
}
}
//关闭所有的DO
public override void CloseAllDO()
{
foreach (string key in mastMap.Keys)
{
byte[] data = new byte[] { 0, 0 };
WriteMultipleDO(key, DefualtSlaveID, DoStartAddress, LineManager.Config.GetDOLength(key), data);
}
}
public override void CloseAllConnection()
{
foreach (MasterTcpClient tcp in mastMap.Values)
{
tcp.disconnect();
}
mastMap.Clear();
timer.Stop();
timer = null;
}
public static void CloseAllDO(string ioIp, byte slaveId)
{
ushort length = LineManager.Config.GetDOLength(ioIp);
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++)
{
bytes[i] = 0;
}
WriteMultipleDO(ioIp, slaveId, DoStartAddress, length, bytes);
}
public static void WriteMultipleDO(string ioIp, byte slaveId, ushort StartAddress, ushort length, byte[] bytes)
{
ushort ID = 6;
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
MBmaster.WriteMultipleCoils(ID, StartAddress, length, bytes, slaveId);
}
else
{
LogUtil.error(LOGGER, "WriteMultipleDO 出错 没有连接IO模块:" + ioIp);
}
}
public override void WriteSingleDO(string ioIp, byte slaveId, ushort StartAddress, IO_VALUE onOff)
{
ushort ID = 5;
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
MBmaster.WriteSingleCoils(ID, StartAddress, onOff, slaveId);
KNDIO io = new KNDIO(ioIp, slaveId, StartAddress, onOff);
SaveDOValue(io, ioIp);
}
else
{
LogUtil.error(LOGGER, "WriteSingleDO 出错没有连接IO模块:" + ioIp);
}
}
public override void WriteSingleDO(string ioIp, byte slaveId, ushort StartAddress, IO_VALUE onOff, int mSeconds)
{
ushort ID = 5;
MasterTcpClient MBmaster = null;
if (mastMap.ContainsKey(ioIp))
{
MBmaster = mastMap[ioIp];
MBmaster.WriteSingleCoils(ID, StartAddress, onOff, slaveId);
KNDIO io = new KNDIO(ioIp, slaveId, StartAddress, onOff);
SaveDOValue(io, ioIp);
//写入之后,等待指定间隔后回写
System.Timers.Timer mytimer = new System.Timers.Timer(mSeconds);
mytimer.Elapsed += (o1, e1) =>
{
try
{
IO_VALUE newValue = IO_VALUE.LOW;
if (onOff.Equals(IO_VALUE.LOW))
{
newValue = IO_VALUE.HIGH;
}
MBmaster.WriteSingleCoils(ID, StartAddress, newValue, slaveId);
KNDIO newIo = new KNDIO(ioIp, slaveId, StartAddress, newValue);
SaveDOValue(newIo, ioIp);
LogUtil.info(LOGGER, "**********定时回写入 IO【" + ioIp + "," + StartAddress + ",值" + onOff + "】:");
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "**********定时回写入 出错:" + ex.StackTrace);
}
};
mytimer.AutoReset = false;//设置是否自动重启,即自动执行多次;
mytimer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件mytask;
}
else
{
LogUtil.error(LOGGER, "WriteSingleDO出错 没有连接IO模块:" + ioIp);
}
}
private static void SaveDOValue(KNDIO io, string ioIp)
{
try
{
lock (DOMapLock)
{
if (!DOValueMap.ContainsKey(ioIp))
{
DOValueMap.Add(ioIp, new List<KNDIO>());
DOValueMap[ioIp].Add(io);
}
else
{
List<KNDIO> ios = DOValueMap[ioIp];
List<KNDIO> list = (from m in ios where m.SlaveId.Equals(io.SlaveId) && m.IOAddress.Equals(io.IOAddress) select m).ToList<KNDIO>();
if (list.Count > 0)
{
DOValueMap[ioIp].Remove(list[0]);
DOValueMap[ioIp].Add(io);
}
else
{
DOValueMap[ioIp].Add(io);
}
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "SaveDOValue出错:" + ex.ToString());
}
}
public override IO_VALUE GetDOValue(string ioIP, byte slaveId, ushort StartAddress)
{
IO_VALUE value = IO_VALUE.LOW;
if (DOValueMap.ContainsKey(ioIP))
{
List<KNDIO> allIo = new List<KNDIO>(DOValueMap[ioIP]);
List<KNDIO> list = (from m in allIo where m.SlaveId.Equals(slaveId) && m.IOAddress.Equals(StartAddress) select m).ToList<KNDIO>();
if (list.Count > 0)
{
value = list[0].IoValue;
}
}
return value;
}
public override IO_VALUE GetDIValue(string ioIP, byte slaveId, ushort StartAddress)
{
IO_VALUE value = IO_VALUE.LOW;
if (DIValueMap.ContainsKey(ioIP))
{
List<KNDIO> allIo = new List<KNDIO>(DIValueMap[ioIP]);
List<KNDIO> list = (from m in allIo where m.SlaveId.Equals(slaveId) && m.IOAddress.Equals(StartAddress) select m).ToList<KNDIO>();
if (list.Count > 0)
{
value = list[0].IoValue;
}
}
return value;
}
public override IO_VALUE GetIOValue(ConfigIO configIO)
{
IO_VALUE value = IO_VALUE.LOW;
try
{
if (configIO.ProType.Equals(ConfigItemType.DI))
{
if (DIValueMap.ContainsKey(configIO.IO_IP))
{
List<KNDIO> allIo = new List<KNDIO>(DIValueMap[configIO.IO_IP]);
List<KNDIO> list = (from m in allIo where m.IOAddress.Equals(configIO.GetIOAddr()) select m).ToList<KNDIO>();
if (list.Count > 0)
{
value = list[0].IoValue;
}
}
}
else if (configIO.ProType.Equals(ConfigItemType.DO))
{
if (DOValueMap.ContainsKey(configIO.IO_IP))
{
List<KNDIO> allIo = new List<KNDIO>(DOValueMap[configIO.IO_IP]);
List<KNDIO> list = (from m in allIo where m.SlaveId.Equals(configIO.SlaveID) && m.IOAddress.Equals(configIO.GetIOAddr()) select m).ToList<KNDIO>();
if (list.Count > 0)
{
value = list[0].IoValue;
}
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "获取数据出错:" + ex.ToString());
}
return value;
}
private static void SaveDIData(string ioIp, ushort ID, byte[] values)
{
try
{
ushort DILength = LineManager.Config.GetDILength(ioIp);
string finalData = "";
if (values.Length == 2 && DILength.Equals(16))
{
string finalData0 = Convert.ToString(values[0], 2).PadLeft(8, '0');
string finalData1 = Convert.ToString(values[1], 2).PadLeft(8, '0');
finalData = finalData1 + finalData0;
}
else if (values.Length == 1 && DILength <= 8)
{
finalData = Convert.ToString(values[0], 2).PadLeft(DILength, '0');
}
LOGGER.Debug("IO模块【" + ioIp + "】收到DI上传:【" + finalData + "】");
if (finalData.Length >= DILength)
{
List<KNDIO> kndList = new List<KNDIO>();
ushort index = (ushort)(DIStartAddress + DILength - 1);
foreach (char str in finalData)
{
KNDIO io = null;
if (str.Equals('1'))
{
io = new KNDIO(ioIp, (byte)ID, index, IO_VALUE.HIGH);
}
else
{
io = new KNDIO(ioIp, (byte)ID, index, IO_VALUE.LOW);
}
kndList.Add(io);
index--;
}
lock (DIMapLock)
{
if (DIValueMap.ContainsKey(ioIp))
{
DIValueMap.Remove(ioIp);
}
DIValueMap.Add(ioIp, kndList);
}
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "SaveDIData出错:" + ex.ToString());
//LOGGER.Error("处理接受数据出错:", ex);
}
}
private static void SaveDOData(string ioIp, ushort ID, byte[] values)
{
ushort DoLength = LineManager.Config.GetDOLength(ioIp);
string finalData = "";
if (values.Length == 2 && DoLength.Equals(16))
{
string finalData0 = Convert.ToString(values[0], 2).PadLeft(8, '0');
string finalData1 = Convert.ToString(values[1], 2).PadLeft(8, '0');
finalData = finalData1 + finalData0;
}
else if (values.Length == 1 && DoLength <= 8)
{
finalData = Convert.ToString(values[0], 2).PadLeft(DoLength, '0');
}
if (finalData.Length >= DoLength)
{
List<KNDIO> kndList = new List<KNDIO>();
ushort index = (ushort)(DoStartAddress + DoLength - 1);
foreach (char str in finalData)
{
KNDIO io = null;
if (str.Equals('1'))
{
io = new KNDIO(ioIp, (byte)ID, index, IO_VALUE.HIGH);
}
else
{
io = new KNDIO(ioIp, (byte)ID, index, IO_VALUE.LOW);
}
kndList.Add(io);
index--;
}
lock (DOMapLock)
{
if (DOValueMap.ContainsKey(ioIp))
{
DOValueMap.Remove(ioIp);
}
DOValueMap.Add(ioIp, kndList);
}
}
}
// ------------------------------------------------------------------------
// Event for response data
// ------------------------------------------------------------------------
private static void MBmaster_OnResponseData(string ioIp, ushort ID, byte function, byte[] values, byte[] reviceData)
{
try
{
if (ioIp.IndexOf(":") > 0)
{
ioIp = ioIp.Substring(0, ioIp.IndexOf(":"));
}
string reviceMsg = "";
foreach (byte data in reviceData)
{
reviceMsg = reviceMsg + " " + data;
if (reviceMsg.Length > 200)
{
break;
}
}
if (ID == 0xFF)
{
return;
}
// ------------------------------------------------------------------------
// Identify requested data
ushort Func = ID;
if (Func == 0 && reviceData.Length > 8)
{
Func = reviceData[7];
}
byte SlaveId = 0xFF;
if (reviceData.Length >= 7)
{
SlaveId = reviceData[6];
}
switch (Func)
{
case 1:
LOGGER.Info("Read coils end:【" + reviceMsg + "】 ");
SaveDOData(ioIp, SlaveId, values);
break;
case 2:
//LOGGER.Info("Read discrete inputs end:【" + reviceMsg + "】 ");
SaveDIData(ioIp, SlaveId, values);
break;
case 3:
//LOGGER.Info("读入(多个)寄存器完成 end:【" + reviceMsg + "】 ");
break;
case 4:
//LOGGER.Info("读入(多个)寄存器完成 end:【" + reviceMsg + "】 ");
break;
case 5:
//LOGGER.Info("Write single coil:【" + reviceMsg + "】 ");
break;
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "处理接受数据出错:" + ex.ToString());
//LOGGER.Error("处理接受数据出错:", ex);
}
}
// ------------------------------------------------------------------------
// Modbus TCP slave exception
// ------------------------------------------------------------------------
private static void MBmaster_OnException(string ioIp, ushort id, byte function, byte exception, byte[] reviceData)
{
string exc = "Modbus says error: ";
switch (exception)
{
case MasterTcpClient.excIllegalFunction: exc += "Illegal function!"; break;
case MasterTcpClient.excIllegalDataAdr: exc += "Illegal data adress!"; break;
case MasterTcpClient.excIllegalDataVal: exc += "Illegal data value!"; break;
case MasterTcpClient.excSlaveDeviceFailure: exc += "Slave device failure!"; break;
case MasterTcpClient.excAck: exc += "Acknoledge!"; break;
case MasterTcpClient.excSlaveIsBusy: exc += "Slave is busy!"; break;
case MasterTcpClient.excGatePathUnavailable: exc += "Gateway path unavailbale!"; break;
case MasterTcpClient.excExceptionTimeout: exc += "Slave timed out!"; break;
case MasterTcpClient.excExceptionConnectionLost: exc += "Connection is lost!"; break;
case MasterTcpClient.excExceptionNotConnected: exc += "Not connected!"; break;
default:
break;
}
LOGGER.Error("接收数据出错:" + exc);
//MessageBox.Show(exc, "Modbus slave exception");
}
}
public class KNDIO
{
public KNDIO(string ioIp, byte ID, ushort index, IO_VALUE o_VALUE)
{
this.IoIP = ioIp;
this.SlaveId = ID;
this.IOAddress = index;
this.IoValue = o_VALUE;
UpdateTime = DateTime.Now;
}
/// <summary>
/// IO模块IP
/// </summary>
public string IoIP { get; set; }
/// <summary>
/// 地址
/// </summary>
public byte SlaveId { get; set; }
/// <summary>
/// 寄存器地址
/// </summary>
public ushort IOAddress { get; set; }
/// <summary>
/// 值
/// </summary>
public IO_VALUE IoValue { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
}
}
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using log4net;
using System.Reflection;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
namespace OnlineStore.DeviceLibrary
{
public class MasterTcpClient
{
public static readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// ------------------------------------------------------------------------
// Constants for access
private const byte fctReadCoil = 1;
private const byte fctReadDiscreteInputs = 2;
private const byte fctReadHoldingRegister = 3;
private const byte fctReadInputRegister = 4;
private const byte fctWriteSingleCoil = 5;
private const byte fctWriteSingleRegister = 6;
private const byte fctWriteMultipleCoils = 15;
private const byte fctWriteMultipleRegister = 16;
private const byte fctReadWriteMultipleRegister = 23;
/// <summary>Constant for exception illegal function.</summary>
public const byte excIllegalFunction = 1;
/// <summary>Constant for exception illegal data address.</summary>
public const byte excIllegalDataAdr = 2;
/// <summary>Constant for exception illegal data value.</summary>
public const byte excIllegalDataVal = 3;
/// <summary>Constant for exception slave device failure.</summary>
public const byte excSlaveDeviceFailure = 4;
/// <summary>Constant for exception acknowledge.</summary>
public const byte excAck = 5;
/// <summary>Constant for exception slave is busy/booting up.</summary>
public const byte excSlaveIsBusy = 6;
/// <summary>Constant for exception gate path unavailable.</summary>
public const byte excGatePathUnavailable = 10;
/// <summary>Constant for exception not connected.</summary>
public const byte excExceptionNotConnected = 253;
/// <summary>Constant for exception connection lost.</summary>
public const byte excExceptionConnectionLost = 254;
/// <summary>Constant for exception response timeout.</summary>
public const byte excExceptionTimeout = 255;
/// <summary>Constant for exception wrong offset.</summary>
private const byte excExceptionOffset = 128;
/// <summary>Constant for exception send failt.</summary>
private const byte excSendFailt = 100;
// ------------------------------------------------------------------------
// Private declarations
private static ushort _timeout = 500;
private static ushort _refresh = 10;
private static bool _connected = false;
private static bool _autoConnectOfBreak = false;
private Socket socketClient;
private int M281_A_Len = 0;
private byte[] tcpSocketReviceBuffer = new byte[2048];
//private Socket tcpSynCl;
//private byte[] tcpSynClBuffer = new byte[2048];
// ------------------------------------------------------------------------
/// <summary>Response data event. This event is called when new data arrives</summary>
public delegate void ResponseData(string ip, ushort id, byte function, byte[] data, byte[] reviceData);
/// <summary>Response data event. This event is called when new data arrives</summary>
public event ResponseData OnResponseData;
/// <summary>Exception data event. This event is called when the data is incorrect</summary>
public delegate void ExceptionData(string ip, ushort id, byte function, byte exception, byte[] reviceData);
/// <summary>Exception data event. This event is called when the data is incorrect</summary>
public event ExceptionData OnException;
/// <summary>
/// autoConnectOfBreak
/// </summary>
public bool autoConnectOfBreak
{
get { return _autoConnectOfBreak; }
set { _autoConnectOfBreak = value; }
}
public static ushort timeout
{
get { return _timeout; }
set { _timeout = value; }
}
public ushort refresh
{
get { return _refresh; }
set { _refresh = value; }
}
public bool connected
{
get { return _connected; }
}
public MasterTcpClient()
{
}
private string IP = "";
public int TimeOutTime = 0;
public MasterTcpClient(string ip, ushort port)
{
this.IP = ip;
TimeOutTime = 2000;
connect(ip, port);
}
private System.Timers.Timer reviceTimer = new System.Timers.Timer();
public void connect(string ip, ushort port)
{
try
{
// Connect asynchronous client
socketClient = new Socket(IPAddress.Parse(ip).AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (TimeOutTime <= 0)
{
socketClient.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout);
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout);
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
}
else
{
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout);
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout);
socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
IAsyncResult connResult = socketClient.BeginConnect(ip, port, null, null);
connResult.AsyncWaitHandle.WaitOne(this.TimeOutTime, true); //等待2秒
if (!connResult.IsCompleted)
{
LogUtil.info(LOGGER, "Connect to " + ip + ":" + port + " fail!");
return;
}
else
{
_connected = true;
}
}
//Thread threadReceive = new Thread(new ThreadStart(ReceiveHandle));
//threadReceive.Start();
reviceTimer.AutoReset = true;
reviceTimer.Elapsed += reviceTimer_Elapsed;
reviceTimer.Interval = 130;
reviceTimer.Enabled = true;
_connected = true;
}
catch (System.IO.IOException error)
{
LogUtil.info(LOGGER, "Connect to " + ip + ":" + port + " fail!");
_connected = false;
throw (error);
}
}
void reviceTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
//socketClient.BeginReceive(tcpSocketReviceBuffer, 0, tcpSocketReviceBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceive), socketClient);
ReviceDataProcess();
Thread.Sleep(10);
}
catch (Exception ex)
{
LOGGER.Error("IO模块[" + IP + "]出错:" + ex.ToString());
}
}
private void ReviceDataProcess()
{
int lengthIndex = 5;
byte[] rdata = Receive();
if (rdata != null)
{
string str = "";
foreach (byte by in rdata)
{
str = str + " " + by;
if (str.Length > 200)
{
break;
}
}
//这里rdata就是接收到的数据,
IPEndPoint clientipe = (IPEndPoint)socketClient.RemoteEndPoint;
//ushort id = BitConverter.ToUInt16(rdata, 0);
//byte function = rdata[7];
byte dataLength = rdata[lengthIndex];
int allLength = lengthIndex + 1 + dataLength;
if (rdata.Length > allLength)
{
//LogUtil.info(clientipe.ToString() + "收到数据(需要分包):" + str);
int currStartIndex = 0;
for (int i = 0; i < 100; i++)
{
try
{
if (rdata.Length < currStartIndex + lengthIndex)
{
LogUtil.error(clientipe.ToString() + "收到数据:" + str + "分包出错 [" + currStartIndex + "]");
}
dataLength = rdata[currStartIndex + lengthIndex];
allLength = lengthIndex + 1 + dataLength;
byte[] thisData = new byte[allLength];
Array.Copy(rdata, currStartIndex, thisData, 0, allLength);
ushort id = BitConverter.ToUInt16(thisData, 0);
byte function = thisData[7];
DataProcess(clientipe.ToString(), id, function, thisData);
//剩余的数据处理
if (rdata.Length <= currStartIndex + allLength)
{
break;
}
currStartIndex = currStartIndex + allLength;
}
catch (Exception ex)
{
LogUtil.error(clientipe.ToString() + "收到数据:" + str + "分包出错 [" + currStartIndex + "]:" + ex.ToString());
}
}
}
else
{
LogUtil.debug(LOGGER, clientipe.ToString() + "收到数据(无需分包):" + str);
ushort id = BitConverter.ToUInt16(rdata, 0);
byte function = rdata[7];
DataProcess(clientipe.ToString(), id, function, rdata);
}
}
}
private void DataProcess(string clientIp, ushort id, byte function, byte[] rdata)
{
byte[] data;
if ((function >= fctWriteSingleCoil) && (function != fctReadWriteMultipleRegister))
{
data = new byte[2];
Array.Copy(rdata, 10, data, 0, 2);
}
// ------------------------------------------------------------
// Read response data
else
{
data = new byte[rdata[8]];
Array.Copy(rdata, 9, data, 0, rdata[8]);
}
// ------------------------------------------------------------
// Response data is slave exception
if (function > excExceptionOffset)
{
function -= excExceptionOffset;
CallException(id, function, rdata[8], rdata);
}
// ------------------------------------------------------------
// Response data is regular data
else if (OnResponseData != null)
{ //收到的数据打印出来
OnResponseData(clientIp, id, function, data, rdata);
}
}
private byte[] Receive()
{
try
{
if (socketClient == null || !socketClient.Connected || socketClient.Available < 1)
{
return null;
}
int size = socketClient.Available;
byte[] rData = new byte[size];
socketClient.Receive(rData, size, SocketFlags.None);
return rData;
}
catch (SocketException e)
{
LogUtil.error(LOGGER, "IO模块[" + IP + "]接收数据出现错误:" + e.ToString());
if (socketClient != null)
{
socketClient.Close();
socketClient = null;
}
return null;
}
}
// ------------------------------------------------------------------------
/// <summary>Stop connection to slave.</summary>
public void disconnect()
{
Dispose();
}
// ------------------------------------------------------------------------
/// <summary>Destroy master instance.</summary>
~MasterTcpClient()
{
Dispose();
}
// ------------------------------------------------------------------------
/// <summary>Destroy master instance</summary>
public void Dispose()
{
reviceTimer.Enabled = false;
if (socketClient != null)
{
if (socketClient.Connected)
{
try
{
socketClient.Shutdown(SocketShutdown.Both);
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "IO模块[" + IP + "]dispose出错:" + ex.ToString());
}
socketClient.Close();
}
socketClient = null;
}
}
internal void CallException(ushort id, byte function, byte exception, byte[] rdata)
{
reviceTimer.Enabled = false;
if ((socketClient == null))
{
return;
}
if (exception == excExceptionConnectionLost)
{
//tcpSynCl = null;
socketClient = null;
return;
}
if (OnException != null)
{
OnException(socketClient.RemoteEndPoint.AddressFamily.ToString(), id, function, exception, rdata);
}
}
public void ReadCoils(ushort id, ushort startAddress, ushort numInputs, byte SlaveID)
{
WriteAsyncData(CreateReadHeader(id, startAddress, numInputs, fctReadCoil, SlaveID), id);
}
public void ReadDiscreteInputs(ushort id, ushort startAddress, ushort numInputs, byte SlaveID)
{
WriteAsyncData(CreateReadHeader(id, startAddress, numInputs, fctReadDiscreteInputs, SlaveID), id);
}
public void ReadHoldingRegister(ushort id, ushort startAddress, ushort numInputs, byte SlaveID)
{
WriteAsyncData(CreateReadHeader(id, startAddress, numInputs, fctReadHoldingRegister, SlaveID), id);
}
public void ReadInputRegister(ushort id, ushort startAddress, ushort numInputs, byte SlaveID)
{
WriteAsyncData(CreateReadHeader(id, startAddress, numInputs, fctReadInputRegister, SlaveID), id);
}
public void WriteSingleCoils(ushort id, ushort startAddress, IO_VALUE ioValue, byte SlaveID)
{
byte[] data;
bool OnOff = ioValue.Equals(IO_VALUE.HIGH);
data = CreateWriteHeader(id, startAddress, 1, 1, fctWriteSingleCoil, SlaveID);
if (OnOff == true) data[10] = 255;
else data[10] = 0;
WriteAsyncData(data, id);
}
public void WriteMultipleCoils(ushort id, ushort startAddress, ushort numBits, byte[] values, byte SlaveID)
{
byte numBytes = Convert.ToByte(values.Length);
byte[] data;
data = CreateWriteHeader(id, startAddress, numBits, (byte)(numBytes + 2), fctWriteMultipleCoils, SlaveID);
Array.Copy(values, 0, data, 13, numBytes);
WriteAsyncData(data, id);
}
public void WriteSingleRegister(ushort id, ushort startAddress, byte[] values, byte SlaveID)
{
byte[] data;
data = CreateWriteHeader(id, startAddress, 1, 1, fctWriteSingleRegister, SlaveID);
data[10] = values[0];
data[11] = values[1];
WriteAsyncData(data, id);
}
public void WriteMultipleRegister(ushort id, ushort startAddress, byte[] values, byte SlaveID)
{
ushort numBytes = Convert.ToUInt16(values.Length);
if (numBytes % 2 > 0) numBytes++;
byte[] data;
data = CreateWriteHeader(id, startAddress, Convert.ToUInt16(numBytes / 2), Convert.ToUInt16(numBytes + 2), fctWriteMultipleRegister, SlaveID);
Array.Copy(values, 0, data, 13, values.Length);
WriteAsyncData(data, id);
}
public void ReadWriteMultipleRegister(ushort id, ushort startReadAddress, ushort numInputs, ushort startWriteAddress, byte SlaveID, byte[] values)
{
ushort numBytes = Convert.ToUInt16(values.Length);
if (numBytes % 2 > 0) numBytes++;
byte[] data;
data = CreateReadWriteHeader(id, startReadAddress, numInputs, startWriteAddress, Convert.ToUInt16(numBytes / 2), SlaveID);
Array.Copy(values, 0, data, 17, values.Length);
WriteAsyncData(data, id);
}
// ------------------------------------------------------------------------
// Create modbus header for read action
private byte[] CreateReadHeader(ushort id, ushort startAddress, ushort length, byte function, byte SlaveID)
{
byte[] data = new byte[12];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[0]; // Slave id high byte
data[1] = _id[1]; // Slave id low byte
data[5] = 6; // Message size
data[6] = SlaveID; // Slave address //必须设置为"1": 2012.04-24 覃发光;
data[7] = function; // Function code
byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));
data[8] = _adr[0]; // Start address
data[9] = _adr[1]; // Start address
byte[] _length = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)length));
data[10] = _length[0]; // Number of data to read
data[11] = _length[1]; // Number of data to read
return data;
}
// ------------------------------------------------------------------------
// Create modbus header for write action
private byte[] CreateWriteHeader(ushort id, ushort startAddress, ushort numData, ushort numBytes, byte function, byte SlaveID)
{
byte[] data = new byte[numBytes + 11];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[0]; // Slave id high byte
data[1] = _id[1]; // Slave id low byte+
byte[] _size = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)(5 + numBytes)));
data[4] = _size[0]; // Complete message size in bytes
data[5] = _size[1]; // Complete message size in bytes
data[6] = SlaveID; // Slave address //必须设置为"1": 2012.04-24 覃发光;
data[7] = function; // Function code
byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));
data[8] = _adr[0]; // Start address
data[9] = _adr[1]; // Start address
if (function >= fctWriteMultipleCoils)
{
byte[] _cnt = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)numData));
data[10] = _cnt[0]; // Number of bytes
data[11] = _cnt[1]; // Number of bytes
data[12] = (byte)(numBytes - 2);
}
return data;
}
// ------------------------------------------------------------------------
// Create modbus header for write action
private byte[] CreateReadWriteHeader(ushort id, ushort startReadAddress, ushort numRead, ushort startWriteAddress, ushort numWrite, byte SlaveID)
{
byte[] data = new byte[numWrite * 2 + 17];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[0]; // Slave id high byte
data[1] = _id[1]; // Slave id low byte+
byte[] _size = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)(11 + numWrite * 2)));
data[4] = _size[0]; // Complete message size in bytes
data[5] = _size[1]; // Complete message size in bytes
data[6] = SlaveID; // Slave address //必须设置为"1": 2012.04-24 覃发光;
data[7] = fctReadWriteMultipleRegister; // Function code
byte[] _adr_read = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startReadAddress));
data[8] = _adr_read[0]; // Start read address
data[9] = _adr_read[1]; // Start read address
byte[] _cnt_read = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)numRead));
data[10] = _cnt_read[0]; // Number of bytes to read
data[11] = _cnt_read[1]; // Number of bytes to read
byte[] _adr_write = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startWriteAddress));
data[12] = _adr_write[0]; // Start write address
data[13] = _adr_write[1]; // Start write address
byte[] _cnt_write = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)numWrite));
data[14] = _cnt_write[0]; // Number of bytes to write
data[15] = _cnt_write[1]; // Number of bytes to write
data[16] = (byte)(numWrite * 2);
return data;
}
// ------------------------------------------------------------------------
// Write asynchronous data
private void WriteAsyncData(byte[] write_data, ushort id)
{
if (socketClient == null)
{
LOGGER.Error("发送数据时发现socketClient=null");
return;
}
IPEndPoint clientipe = (IPEndPoint)socketClient.RemoteEndPoint;
if ((socketClient != null) && (socketClient.Connected))
{
try
{
//发送的数据打印出来
string str = "";
foreach (byte by in write_data)
{
str = str + " " + by;
}
//LogUtil.info( clientipe.ToString()+"发送数据:" + str);
socketClient.BeginSend(write_data, 0, write_data.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
//socketClient.BeginReceive(tcpSocketReviceBuffer, 0, tcpSocketReviceBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceive), socketClient);
ReviceDataProcess();
}
catch (SystemException error)
{
LogUtil.error(LOGGER, "IO模块 WriteAsyncData出错:" + error.ToString());
CallException(id, write_data[7], excExceptionConnectionLost, tcpSocketReviceBuffer);
}
}
else CallException(id, write_data[7], excExceptionConnectionLost, tcpSocketReviceBuffer);
}
// ------------------------------------------------------------------------
// Write asynchronous data acknowledge
private void OnSend(System.IAsyncResult result)
{
if (result.IsCompleted == false) CallException(0xFFFF, 0xFF, excSendFailt, tcpSocketReviceBuffer);
}
// ------------------------------------------------------------------------
// Write asynchronous data response
private void OnReceive(System.IAsyncResult result)
{
if (socketClient == null)
{
return;
}
IPEndPoint clientipe = (IPEndPoint)socketClient.RemoteEndPoint;
if (result.IsCompleted == false)
{
CallException(0xFF, 0xFF, excExceptionConnectionLost, tcpSocketReviceBuffer);
}
ushort id = BitConverter.ToUInt16(tcpSocketReviceBuffer, 0); ;
byte function = tcpSocketReviceBuffer[7];
byte[] data;
// ------------------------------------------------------------
// Write response data
if ((function >= fctWriteSingleCoil) && (function != fctReadWriteMultipleRegister))
{
data = new byte[2];
Array.Copy(tcpSocketReviceBuffer, 10, data, 0, 2);
}
// ------------------------------------------------------------
// Read response data
else
{
data = new byte[tcpSocketReviceBuffer[8]];
Array.Copy(tcpSocketReviceBuffer, 9, data, 0, tcpSocketReviceBuffer[8]);
}
// ------------------------------------------------------------
// Response data is slave exception
if (function > excExceptionOffset)
{
function -= excExceptionOffset;
CallException(id, function, tcpSocketReviceBuffer[8], tcpSocketReviceBuffer);
}
// ------------------------------------------------------------
// Response data is regular data
else if (OnResponseData != null)
{ //收到的数据打印出来
string str = "";
foreach (byte by in tcpSocketReviceBuffer)
{
str = str + " " + by;
if (str.Length > 50)
{
break;
}
}
// LogUtil.info( clientipe.ToString()+"收到数据:" + str);
OnResponseData(clientipe.ToString(), id, function, data, tcpSocketReviceBuffer);
}
}
internal bool ISConnection()
{
if (socketClient == null)
{
return false;
}
if (socketClient.Connected == false)
{
return false;
}
return true;
}
}
}
类型,说明,名称,属性值,设备名称,默认值,描述,电器定义,代码定义,SlaveID,
PRO,IO模块对应的DI数量,IO_DILength,10.85.162.17#16,,,,,,,
PRO,模块对应的DO数量,IO_DOLength,10.85.162.17#16,,,,,,,
PRO,IO模块IP,PRO_AOI_IP_1,10.85.162.17,,,,,,,
,,,,,,,,,,
DI,急停,SuddenStop_BTN,0,PRO_AOI_IP_1,0,急停,X01,DI-01,0,
DI,复位,Reset_BTN,1,PRO_AOI_IP_1,0,复位,X02,DI-02,0,
DI,线体入口检测,InCheck,2,PRO_AOI_IP_1,0,线体入口检测,X03,DI-03,0,
DI,线体阻挡检测,StopCheck1,3,PRO_AOI_IP_1,0,线体阻挡检测,X04,DI-04,0
DI,线体出口检测,OutCheck,4,PRO_AOI_IP_1,0,线体出口检测,X05,DI-05,0,
DO,运行状态指示灯,AutoRun_HddLed,0,PRO_AOI_IP_1,0,运行状态指示灯,Y01,DO-01,0,
DO,线体驱动电机运转,Line_Run,1,PRO_AOI_IP_1,0,线体驱动电机运转,Y02,DO-02,0,
DO,进料线阻挡下降,StopDown,2,PRO_AOI_IP_1,0,进料线阻挡下降,Y03,DI-03,0,
DO,进料线出口阻挡下降,OutStopDown,3,PRO_AOI_IP_1,0,进料线出口阻挡下降,Y04,DI-04,0,
PRO,IO信号超时时间(毫秒),IOSingle_TimerOut,10000,,,,,,,
PRO,线体入口节点名称,In_AgvName,A2,,,,,,,
PRO,线体出口节点名称,Out_AgvName,A1,,,,,,,
PRO,入口RFIDIP,L2_In_RFIDIP,192.168.103.108,,,,,, ,
PRO,出口RFIDIP,L2_Out_RFIDIP,192.168.103.107,,,,,, ,
PRO,休眠秒数(秒),SleepSeconds,40,,,,,,,
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("DeviceLibrary")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DeviceLibrary")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("10193426-c259-4528-930a-9bdd47a6c8be")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
using log4net;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Asa.RFID
{
public class RFIDAuto
{
public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");
private string IP = "";
private byte addr;
private int portIndex;
private bool IsConnect = false;
private byte[] lastData = new byte[8];
/// <summary>
/// 接收事件
/// </summary>
/// <param name="ip"></param>
/// <param name="buff"></param>
public delegate void Received_Event(string ip, byte[] buff);
/// <summary>
/// 接收数据
/// </summary>
public event Received_Event Received;
public RFIDAuto(string ip)
{
this.IP = ip;
}
public int StopAutoScan()
{
try
{
IsConnect = false;
byte scanMode = 0;
int ErrCode = SetAutoScanMode(addr, scanMode);
LOGGER.Info("Close RFID [" + IP + "] ScanMode:" + ErrCode);
ErrCode = ReaderA.StaticClassReaderA.CloseNetPort(portIndex);
LOGGER.Info("Close RFID [" + IP + "]:" + ErrCode);
return ErrCode;
}
catch (Exception e)
{
LOGGER.Error("Close RFID[" + IP + "] has error", e);
}
return -1;
}
public int StartAutoScan(Received_Event OnReceive)
{
if (IsConnect)
{
LOGGER.Warn(" RFID [" + IP + "] is already connected, no need to start again");
return 0;
}
this.Received = OnReceive;
//IP合法
string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
bool rtn = System.Text.RegularExpressions.Regex.IsMatch(IP, pattern);
if (!rtn)
{
LOGGER.Error(IP + " is error");
return -1;
}
string[] arr = IP.Split('.');
if (arr.Length != 4)
{
LOGGER.Error(IP + " length is not 4");
return -1;
}
addr = Convert.ToByte(arr[3]);
int port = 6000 + Convert.ToInt32(arr[3]);
portIndex = 0;
int ErrCode = 0;
for (int i = 1; i <= 3; i++)
{
ErrCode = ReaderA.StaticClassReaderA.OpenNetPort(port, IP, ref addr, ref portIndex);
LOGGER.Info("Connect [" + IP + "] :" + ErrCode);
if (ErrCode == 0)
{
ErrCode = OpenAutoScanMode(addr);
LOGGER.Info(" [" + IP + "] Open Auto Scan Mode:" + ErrCode);
Task.Factory.StartNew(AutoScan);
break;
}
else if (i < 3)
{
LOGGER.Error("Connect [" + IP + "] " + ErrCode + ", StopAutoScan");
StopAutoScan();
}
Thread.Sleep(10);
}
return ErrCode;
}
private int SetAutoScanMode(byte addr, byte scanMode)
{
byte[] scanModeData = new byte[11];
//bit0: 0停止扫描,1开始扫描
//bit1: 0正常数据扫描,1EAS扫描
//bit2: 0正常灵敏度,1高灵敏度
//bit3: 0禁止输入同步,1允许输入同步
//bit4: 0禁止指令同步,1允许指令同步
//bit5: 0禁止扫描提示,1允许扫描提示
//bit6: 0禁止EAS探测提示,1允许EAS探测提示
//bit7: 0禁止EAS消息输出提示,1允许EAS消息输出提示
scanModeData[0] = scanMode;
//bit0: 0不发送comAddr,1发送comAddr
//bit1: 0不带UID,1带UID
//bit2: 0不包含指定块,1包含指定块
//bit3: 0不带安全状态字,1带安全状态字
//bit4: 0 ASCII,1 HEX
//bit5: 0不进行开关射频场,1进行开关射频场
//bit6: 0无操作,1停止扫描关闭射频场
//bit7: 0无,1鸣叫闪烁
scanModeData[1] = 255;
scanModeData[2] = 0; //起始块号
scanModeData[3] = 2; //块总数 之前是28
scanModeData[4] = 1; //块的起始字节
scanModeData[5] = 4; //块的字节数
//1 CR+LF 0x0D 0x0A
//2 CR 0x0D
//4 LF 0x0A
//8 BEL 0x07
//16 :(分号) 0x3B
//32 ,(逗号) 0x2C
//64 " "(空格) 0x20
//128 自定义
scanModeData[6] = 8; //间隔符
scanModeData[7] = 0; //自定义间隔符,[6] = 128
//1 CR+LF 0x0D 0x0A
//2 CR 0x0D
//4 LF 0x0A
//8 BEL 0x07
//16 :(分号) 0x3B
//32 ,(逗号) 0x2C
//64 " "(空格) 0x20
//128 自定义
scanModeData[8] = 8; //结束符
scanModeData[9] = 0; //自定义间隔符,[8] = 128
scanModeData[10] = 0x00;
int ErrCode = ReaderA.StaticClassReaderA.SetScanMode(ref addr, scanModeData, portIndex);
return ErrCode;
}
private DateTime LastOkTime = DateTime.Now;
private void AutoScan()
{
IsConnect = true;
byte[] dataBuffer = new byte[0];
while (IsConnect)
{
try
{
byte[] data = new byte[100];
int len = 0;
int ErrCode = ReaderA.StaticClassReaderA.ReadScanModeData(data, ref len, portIndex);
if (ErrCode == 0)
{
LastOkTime = DateTime.Now;
string dataStr = byteToStr(data, len);
if (len > data.Length)
{
LOGGER.Info(IP + " Receive Code: " + ErrCode + " Len: " + len + " Data:" + dataStr);
}
LOGGER.Debug(IP + " Receive Code: " + ErrCode + " Len: " + len + " Data:" + dataStr);
byte[] temp = new byte[dataBuffer.Length + len];
Array.Copy(dataBuffer, temp, dataBuffer.Length);
Array.Copy(data, 0, temp, dataBuffer.Length, len);
byte[] bb = new byte[10];
int idx = -1;
bool start = false;
bool end = false;
int endIndex = -1;
for (int i = 0; i < temp.Length; i++)
{
byte b = temp[i];
if (b == 0x5A)
{
start = true;
idx = 0;
//bb[idx++] = result;
}
else if (b == 0x4A && start)
{
start = false;
end = true;
endIndex = i;
bb[idx++] = b;
}
if (start)
{
if (idx + 1 == bb.Length)
{
start = false;
end = false;
}
else
{
bb[idx++] = b;
}
}
if (end)
{
byte[] _buff = new byte[8];
_buff[0] = bb[0];
_buff[1] = bb[1];
_buff[2] = bb[2];
_buff[3] = bb[3];
_buff[4] = bb[5];
_buff[5] = bb[6];
_buff[6] = 0;
_buff[7] = 0;
end = false;
string itemStr = byteToStr(_buff, _buff.Length);
lastData = _buff;
LOGGER.Debug("[" + IP + "] Item:" + itemStr);
Received?.Invoke(IP, _buff);
}
}
endIndex++;
if (endIndex < temp.Length)
{
dataBuffer = new byte[temp.Length - endIndex];
Array.Copy(temp, endIndex, dataBuffer, 0, temp.Length - endIndex);
dataStr = byteToStr(dataBuffer, dataBuffer.Length);
LOGGER.Debug(IP + " Receive Code: 剩余 Length: " + dataBuffer.Length + " Data:" + dataStr);
}
}
else if (ErrCode == 14 && IsConnect)
{
LOGGER.Error(IP + " Receive Code: " + ErrCode + " 进行重连");
LogUtil.error(IP + " Receive Code: " + ErrCode + " 进行重连");
StopAutoScan();
StartAutoScan(this.Received);
break;
}
else
{
TimeSpan span = DateTime.Now - LastOkTime;
if (span.TotalMinutes > 2)
{
LastOkTime = DateTime.Now;
string dataStr = byteToStr(data, len);
LOGGER.Debug(IP + " Receive Code: " + ErrCode + " Len: " + len + " Data:" + dataStr);
}
}
System.Threading.Thread.Sleep(60);
}
catch (Exception e)
{
LOGGER.Error("ReadScanModeData Error:", e);
}
}
}
public byte[] ReadAndClear()
{
byte[] data = lastData;
lastData = new byte[8];
LOGGER.Debug("Read and clear RFID[" + IP + "] data:" + byteToStr(data, data.Length));
return data;
}
public byte[] Read()
{
return lastData;
}
private int OpenAutoScanMode(byte addr)
{
byte scanMode = 1;
return SetAutoScanMode(addr, scanMode);
}
private string byteToStr(byte[] data, int len)
{
if (data.Length <= len)
{
len = data.Length;
}
string s = "";
for (int i = 0; i < len; i++)
{
s += data[i].ToString("X2") + " ";
}
return s;
}
}
}
using log4net;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Asa.RFID.RFIDAuto;
namespace Asa.RFID
{
public class RFIDAutoReader
{
public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");
private static Dictionary<string, RFIDAuto> rfidMap = new Dictionary<string, RFIDAuto>();
public static Dictionary<string, int> rfidErrorMap = new Dictionary<string, int>();
/// <summary>
/// 打开所有
/// </summary>
/// <param name="ipArr"></param>
/// <param name="OnReceive"></param>
/// <param name="ip"></param>
public static void Open(Received_Event OnReceive, params string[] ipArr)
{
rfidErrorMap = new Dictionary<string, int>();
foreach (var ip in ipArr)
{
int code = 0;
if (rfidMap.ContainsKey(ip))
{
code = rfidMap[ip].StartAutoScan(OnReceive);
}
else
{
RFIDAuto rfid = new RFIDAuto(ip);
code = rfid.StartAutoScan(OnReceive);
rfidMap.Add(ip, rfid);
}
if (rfidErrorMap.ContainsKey(ip))
{
rfidErrorMap.Remove(ip);
}
rfidErrorMap.Add(ip, code);
if (code.Equals(0).Equals(false))
{
LogUtil.error("连接RFID【" + ip + "】ErrorCode=" + code);
}
}
}
public static void ReOpen(string ip)
{
LogUtil.error("ReOpen【" + ip + "】");
int code = 0;
if (rfidMap.ContainsKey(ip))
{
rfidMap[ip].StopAutoScan();
Thread.Sleep(200);
code = rfidMap[ip].StartAutoScan(null);
}
else
{
RFIDAuto rfid = new RFIDAuto(ip);
code = rfid.StartAutoScan(null);
rfidMap.Add(ip, rfid);
}
if (rfidErrorMap.ContainsKey(ip))
{
rfidErrorMap.Remove(ip);
}
rfidErrorMap.Add(ip, code);
if (code.Equals(0).Equals(false))
{
LogUtil.error("连接RFID【" + ip + "】ErrorCode=" + code);
}
}
/// <summary>
/// 获取最后读到的标签并清理
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static byte[] ReadAndClear(string ip)
{
if (rfidMap.ContainsKey(ip))
{
return rfidMap[ip].ReadAndClear();
}
return null;
}
/// <summary>
/// 获取最后读到的标签
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static byte[] Read(string ip)
{
if (rfidMap.ContainsKey(ip))
{
return rfidMap[ip].Read();
}
return null;
}
/// <summary>
/// 关闭所有
/// </summary>
public static void CloseAll()
{
foreach (var rfid in rfidMap.Values)
{
rfid.StopAutoScan();
}
rfidMap = new Dictionary<string, RFIDAuto>();
}
}
}

using Asa.RFID;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OnlineStore.DeviceLibrary
{
public class RFIDManager
{
public static void Open(string[] iparray)
{
try
{
RFIDAutoReader.Open( null,iparray);
}catch(Exception ex)
{
LogUtil.error("Open 出错:" + ex.ToString());
}
}
public static RFIDData ReadRFID(string ip, bool isClear = false)
{
try
{
if (String.IsNullOrEmpty(ip).Equals(false))
{
byte[] bdata = null;
if (isClear)
{
bdata = RFIDAutoReader.ReadAndClear(ip);
}
else
{
bdata = RFIDAutoReader.Read(ip);
}
if (bdata == null)
{
LogUtil.error("RFID [ " + ip + " ] 读到数据=null");
}
RFIDData data = new RFIDData(bdata);
return data;
}
}
catch (Exception ex)
{
//LogUtil.error("ReadRFID["+ip+"]出错:" + ex.ToString());
}
return new RFIDData(0, 0);
}
public static void Close()
{
try
{
RFIDAutoReader.CloseAll();
}
catch (Exception ex)
{
LogUtil.error("关闭RFID出错:" + ex.ToString());
}
}
}
public class RFIDData
{
/// <summary>
/// RFID类型,区分是料架还是托盘,托盘E=69,包装料料架A=65,料串=B
/// </summary>
public char RFType = '0';
public int Num = 0;
public RFIDData(int num, int t)
{
if (t < 65)
{
RFType = '0';
}
else
{
this.RFType = (char)t;
}
this.Num = num;
}
public RFIDData(byte[] data)
{
try
{
if (data != null && data.Length > 2)
{
if (data[1] < 65)
{
RFType = '0';
}
else
{
RFType = (char)data[1];
}
Num = (int)(data[2]);
}
}
catch (Exception ex)
{
LogUtil.error("RFIP 数据【" + data + "】 获取编码失败");
}
}
public byte[] ToData()
{
return new byte[] { (byte)RFType, (byte)Num };
}
public string NumStr()
{
return "" + RFType + "" + Num.ToString() + "";
}
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Asa.RFID.RFID;
namespace Asa.RFID
{
public class RFID
{
public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");
// private System.Threading.Thread tScan;
private bool loop;
private string IP = "";
private byte addr;
private int portIndex;
private bool IsConnect = false;
private byte[] lastData = new byte[8];
internal byte[] _buff; //8字节缓存
private byte[] _uid; //卡片ID
public bool IsExist = false;
public int ErrCode = 0;
/// <summary>
/// 接收事件
/// </summary>
/// <param name="ip"></param>
/// <param name="buff"></param>
public delegate void Received_Event(string ip, byte[] buff);
/// <summary>
/// 接收数据
/// </summary>
public event Received_Event Received;
public RFID(string ip)
{
this.IP = ip;
}
public int Close()
{
try
{
loop = false;
IsConnect = false;
try
{
// tScan.Abort();
}
catch (Exception ex)
{
LOGGER.Info("Close tScan[" + IP + "] error :" + ex.ToString());
}
int ErrCode = ReaderA.StaticClassReaderA.CloseNetPort(portIndex);
LOGGER.Info("Close RFID [" + IP + "]:" + ErrCode);
return ErrCode;
}
catch (Exception e)
{
LOGGER.Error("Close RFID[" + IP + "] has error", e);
}
return -1;
}
public int Open()
{
if (IsConnect)
{
LOGGER.Warn(" RFID [" + IP + "] is already connected, no need to start again");
return 0;
}
//IP合法
string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
bool rtn = System.Text.RegularExpressions.Regex.IsMatch(IP, pattern);
if (!rtn)
{
LOGGER.Error(IP + " is error");
return -1;
}
string[] arr = IP.Split('.');
if (arr.Length != 4)
{
LOGGER.Error(IP + " length is not 4");
return -1;
}
addr = Convert.ToByte(arr[3]);
int port = 6000 + Convert.ToInt32(arr[3]);
portIndex = 0;
int ErrCode = ReaderA.StaticClassReaderA.OpenNetPort(port, IP, ref addr, ref portIndex);
LOGGER.Info("Connect [" + IP + "] :" + ErrCode);
// 在 OpenNetPort 后面使用
System.Threading.Thread.Sleep(100);
OpenCloseRF(false);
System.Threading.Thread.Sleep(100);
OpenCloseRF(true);
return ErrCode;
}
public void FindMode()
{
loop = true;
//tScan = new System.Threading.Thread(new System.Threading.ThreadStart(Scan));
//tScan.Start();
Task.Factory.StartNew(Scan);
}
private void Scan()
{
while (loop)
{
bool rtn = FindRFID();
if (rtn)
{
int result = ReadRFID();
if (result.Equals(0))
{
byte[] bb = new byte[] { _buff[0], _buff[1], _buff[2] };
string dataStr = byteToStr(bb, bb.Length);
LOGGER.Info(IP + " Scan Data:" + dataStr);
Received?.Invoke(IP, bb);
}
else if (result.Equals(14))
{
LOGGER.Error(IP + " ReadRFID 返回 " + result + ", 需要重连,调用close ,等待100后重连");
Close();
System.Threading.Thread.Sleep(100);
Open();
FindMode();
break;
}
}
System.Threading.Thread.Sleep(100);
}
}
private void OpenCloseRF(bool rtn)
{
if (rtn)
ErrCode = ReaderA.StaticClassReaderA.OpenRf(ref addr, portIndex);
else
ErrCode = ReaderA.StaticClassReaderA.CloseRf(ref addr, portIndex);
}
/// <summary>
/// 查找电子标签,扫描模式不能使用
/// </summary>
/// <returns></returns>
public bool FindRFID()
{
try
{
//0 不带AFI
//1 带AFI
//2 不带AFI,继续查询
//3 带AFI,继续查询
//6 不带AFI,新的查询
//7 带AFI,新的查询
byte state = 0;
//Select模式需要AFI
byte AFI = 0;
//输出,1字节DSFID,8字节UID
byte[] DSFIDAndUID = new byte[9];
//输出,标签数量
byte cardNumber = 0;
if (_uid == null)
{
_uid = new byte[8];
}
ErrCode = ReaderA.StaticClassReaderA.Inventory(ref addr, ref state, ref AFI, DSFIDAndUID, ref cardNumber, portIndex);
if (ErrCode == 0)
{
//查询时间
//fCmdRet = StaticClassReaderA.GetInventoryTime(ref n_time, portIndex);
Array.Copy(DSFIDAndUID, 1, _uid, 0, 8);
IsExist = true;
return true;
}
else
{
for (int i = 0; i < _uid.Length; i++)
_uid[i] = 0;
IsExist = false;
}
}
catch (Exception ex)
{
LOGGER.Error(IP + "FindRFID Error:" + ex.ToString());
}
return false;
}
//public byte[] Read(bool isNeedFind = false)
//{
// if (isNeedFind)
// {
// FindRFID();
// }
// if (IsExist)
// {
// ReadRFID();
// return _buff;
// }
// else
// {
// LOGGER.Info(IP + " Read: IsExist=false ");
// }
// return null;
//}
private int ReadRFID()
{
try
{
//0 不带AFI
//1 带AFI
//2 不带AFI,继续查询
//3 带AFI,继续查询
//6 不带AFI,新的查询
//7 带AFI,新的查询
byte state = 0;
//起始块号
byte blockNum = 0;
//块数量
byte blockCount = 2;
//输出,块内安全信息,长度为BlockCount个字节
byte[] blockSecStatus = new byte[blockCount];
//输出,块内数据信息,长度为块的大小(4或8字节)乘以BlockCount个字节
byte[] data = new byte[4 * blockCount];
//错误代码
byte errorCode = 0;
if (_buff == null)
{
_buff = new byte[8];
}
ErrCode = ReaderA.StaticClassReaderA.ReadMultipleBlock(ref addr, ref state, _uid, blockNum, blockCount, blockSecStatus, data, ref errorCode, portIndex);
if (ErrCode == 0)
{
Array.Copy(data, 0, _buff, 0, data.Length);
string dataStr = byteToStr(data, data.Length);
LOGGER.Info(IP + " ReadMultipleBlock: Length: " + data.Length + " Data:" + dataStr);
}
else if (ErrCode == 14)
{
LOGGER.Error(IP + " ReadMultipleBlock: ErrCode: " + ErrCode + ",需要重连");
}
else
{
LOGGER.Info(IP + " ReadMultipleBlock: ErrCode: " + ErrCode);
}
return ErrCode;
}
catch (Exception ex)
{
LOGGER.Error(IP + "ReadRFID Error:" + ex.ToString());
}
return -1;
}
private string byteToStr(byte[] data, int len)
{
string s = "";
for (int i = 0; i < len; i++)
{
s += data[i].ToString("X2") + " ";
}
return s;
}
}
public class RFIDReader
{
public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");
private static Dictionary<string, RFID> rfidMap = new Dictionary<string, RFID>();
private static Dictionary<string, byte[]> LastRfidData = new Dictionary<string, byte[]>();
public static void Open(params string[] ipArr)
{
try
{
foreach (var ip in ipArr)
{
if (rfidMap.ContainsKey(ip))
{
rfidMap[ip].Open();
rfidMap[ip].FindMode();
}
else
{
RFID rfid = new RFID(ip);
rfid.Received += Rfid_Received;
rfid.Open();
rfid.FindMode();
rfidMap.Add(ip, rfid);
}
}
}
catch (Exception ex)
{
LOGGER.Error("RFIDReader Open Error:" + ex.ToString());
}
}
private static void Rfid_Received(string ip, byte[] buff)
{
if (buff == null)
{
return;
}
string dataStr = byteToStr(buff, buff.Length);
LOGGER.Info(ip + " Rfid_Received 保存数据:" + dataStr);
if (LastRfidData.ContainsKey(ip))
{
LastRfidData[ip] = buff;
}
else
{
LastRfidData.Add(ip, buff);
}
}
//public static bool FindRFID(string ip)
//{
// if (rfidMap.ContainsKey(ip))
// {
// return rfidMap[ip].FindRFID();
// }
// return false;
//}
public static byte[] Read(string ip, bool isClear = false)
{
if (rfidMap.ContainsKey(ip))
{
if (LastRfidData.ContainsKey(ip))
{
byte[] data = LastRfidData[ip];
if (isClear)
{
LastRfidData.Remove(ip);
}
return data;
}
// return rfidMap[ip].Read(isNeedFind);
}
return null;
}
public static void CloseAll()
{
foreach (RFID rfid in rfidMap.Values)
{
rfid.Close();
}
}
private static string byteToStr(byte[] data, int len)
{
string s = "";
for (int i = 0; i < len; i++)
{
s += data[i].ToString("X2") + " ";
}
return s;
}
}
}
using Asa.RFID;
using OnlineStore.Common;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
public class RFIDManager
{
private static ReadAll readAll =new ReadAll ("TheRFID");
private static bool IsOpen = false;
// private static ConcurrentDictionary<string, string> LastRfidMap = new ConcurrentDictionary<string, string>();
public static void Open(string[] iparray)
{
if (IsOpen)
{
return;
}
try
{
int port = ConfigAppSettings.GetIntValue(Setting_Init.RfidServer_Port);
if (port <= 0)
{
port = 13001;
}
// readAll.Received += ReadAll_Received;
// readAll.Log += ReadAll_Log;
LogUtil.info("RFID Server Open,port=" + port);
readAll.Start(port);
IsOpen = true;
}
catch (Exception ex)
{
LogUtil.error("Open 出错:" + ex.ToString());
}
}
private static string lastStr = "";
private static void ReadAll_Log(string ip, string log)
{
string str = "RFID : [" + ip + "] " + log;
if (lastStr.Equals(str))
{
return;
}
LogUtil.info(str);
lastStr = str;
}
public static RFIDData ReadRFID(string ip, bool isClear = false)
{
try
{
if (String.IsNullOrEmpty(ip).Equals(false))
{
string outValue = readAll.Read(ip);
if (isClear)
{
readAll.Clear(ip);
}
RFIDData data = new RFIDData(outValue);
return data;
}
}
catch (Exception ex)
{
LogUtil.error("ReadRFID[" + ip + "] [" + isClear + "] 出错:" + ex.ToString());
}
return new RFIDData();
}
public static void Close()
{
try
{
readAll.Stop();
}
catch (Exception ex)
{
LogUtil.error("关闭RFID出错:" + ex.ToString());
}
}
}
public class RFIDData
{
public string StrData = "";
public RFIDData(string data = "00")
{
if (String.IsNullOrEmpty(data))
{
data = "00";
}
this.StrData = data;
}
public string NumStr()
{
return StrData;
}
internal static bool IsRealRfid(string shelfRfid)
{
//判断料架号是否是真实的料架号
if (shelfRfid.StartsWith("C") || shelfRfid.StartsWith("D"))
{
int num = -1;
try
{
num = Convert.ToInt32(shelfRfid.Substring(1, shelfRfid.Length - 1));
}
catch (Exception ex)
{
}
if (num > 0)
{
return true;
}
}
return false;
}
}
}
文件属性发生变化

using Asa;
using AsaPL;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
public partial class LineBean
{
public LineConfig Config;
public bool IsDebug = false;
public string Name = "";
public bool isInSuddenDown = false;
public LineMoveInfo MoveInfo = null;
public AlarmType alarmType = AlarmType.None;
public RunStatus runStatus = RunStatus.Wait;
public AgvClient_Line AgvClient;
public string WarnMsg = "";
private System.Timers.Timer serverConnectTimer = new System.Timers.Timer();
private System.Timers.Timer mainTimer = new System.Timers.Timer();
public LineBean(LineConfig config)
{
serverConnectTimer = new System.Timers.Timer();
serverConnectTimer.Interval = 1000;
serverConnectTimer.AutoReset = true;
serverConnectTimer.Enabled = false;
//serverConnectTimer.Elapsed += server_connect_timer_Tick;
mainTimer = new System.Timers.Timer();
mainTimer.Interval = 300;
mainTimer.AutoReset = true;
mainTimer.Enabled = false;
mainTimer.Elapsed +=timersTimer_Elapsed;
//添加调试
IsDebug = ConfigAppSettings.GetIntValue(Setting_Init.IsInDebug).Equals(1);
MoveInfo = new LineMoveInfo();
Name = ConfigAppSettings.GetValue(Setting_Init.App_Title).ToUpper();
this.Config = config;
IOManager.Init();
IOManager.instance.ConnectionIOList(Config.DIODeviceNameList);
AgvClient = new AgvClient_Line();
AgvClient.Init(config.In_AgvName, config.Out_AgvName);
mainTimer.Enabled = false;
int isAuto = ConfigAppSettings.GetIntValue(Setting_Init.App_AutoRun);
if (isAuto == 1)
{
mainTimer.Enabled = true;
}
Thread.Sleep(300);
//IOManager.IOMove(IO_Type.Alarm_HddLed, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.AutoRun_HddLed, IO_VALUE.LOW);
}
/// <summary>
/// 开始运行
/// </summary>
public bool StartRun()
{
LogUtil.info(Name + "开始启动,启动时间:" + DateTime.Now);
WarnMsg = "";
if (IOManager.IOValue(IO_Type.SuddenStop_BTN).Equals(IO_VALUE.HIGH))
{
//急停按钮和气压检测需要一起判断
// if (!AgvClient.ISConnected())
// {
//}
AgvClient.SetCancelState(false);
RFIDManager.Open(new string[] { Config.L2_In_RFIDIP, Config.L2_Out_RFIDIP });
runStatus = RunStatus.HomeMoving;
MoveInfo.NewMove(LineMoveType.ReturnHome);
ReturnHome();
return true;
}
else
{
SetWarnMsg("启动失败:急停未开");
return false;
}
}
#region 原点返回和复位处理
private void ReturnHome()
{
isInSuddenDown = false;
alarmType = AlarmType.None;
SetWarnMsg("");
//IOManager.IOMove(IO_Type.Alarm_HddLed, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.AutoRun_HddLed, IO_VALUE.HIGH);
MoveInfo.NextMoveStep(MoveStep.VMI_H_StopUp);
LogUtil.info(Name + " 开始复位:所有阻挡上升,设置状态为None");
MoveInfo.WaitList.Add(WaitResultInfo.WaitTime(500));
IOManager.IOMove(IO_Type.OutStopDown, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.StopDown, IO_VALUE.LOW);
mainTimer.Enabled = true;
serverConnectTimer.Enabled = true;
}
public void Reset(bool isNeedClearAuto = true)
{
if (IOManager.IOValue(IO_Type.SuddenStop_BTN).Equals(IO_VALUE.HIGH))
{
mainTimer.Enabled = false;
serverConnectTimer.Enabled = false;
runStatus = RunStatus.Reset;
MoveInfo.NewMove(LineMoveType.StoreReset);
ReturnHome();
}
else
{
SetWarnMsg("复位失败:急停未开");
}
}
/// <summary>
/// 复位处理
/// </summary>
protected void ResetProcess()
{
if (MoveInfo.IsInWait)
{
CheckWait(MoveInfo);
}
if (MoveInfo.IsInWait)
{
return;
}
switch (MoveInfo.MoveStep)
{
case MoveStep.VMI_H_StopUp:
MoveInfo.NextMoveStep(MoveStep.VMI_H_LineRun);
LogUtil.info(Name + " 复位:阻挡上升完成,转动流水线,停止休眠");
MoveInfo.WaitList.Add(WaitResultInfo.WaitTime(500));
IOManager.IOMove(IO_Type.Line_Run, IO_VALUE.HIGH);
UpdateSleep(false);
break;
case MoveStep.VMI_H_LineRun:
LogUtil.info(Name + " 复位完成");
MoveInfo.EndMove();
runStatus = RunStatus.Runing;
break;
default: break;
}
}
#endregion
/// <summary>
/// 停止运行
/// </summary>
public void StopRun()
{
WarnMsg = "";
RFIDManager.Close();
AgvClient.SetCancelState(true);
mainTimer.Enabled = false;
serverConnectTimer.Enabled = false;
StopMove();
runStatus = RunStatus.Wait;
IOManager.instance.CloseAllDO();
LogUtil.info(Name + ",停止运行");
}
public void Alarm(AlarmType alarmType)
{
if (this.alarmType.Equals(alarmType) && alarmType != AlarmType.SuddenStop )
{
return;
}
LogUtil.error(Name + " 报警,报警类型:" + alarmType);
this.alarmType = alarmType;
if (alarmType.Equals(AlarmType.SuddenStop))
{
isInSuddenDown = true;
LogUtil.error(Name + "收到急停信号,停止运行 ");
MoveInfo.EndMove();
StopMove();
}
}
public void StopMove()
{
IOManager.IOMove(IO_Type.Line_Run, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.StopDown, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.OutStopDown, IO_VALUE.LOW);
IOManager.IOMove(IO_Type.StopDown, IO_VALUE.LOW);
}
private bool InProcess = false;
private Stopwatch stopwatch = new Stopwatch();
public bool MoveStop = false;
protected void timersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (MoveStop)
{
return;
}
if (InProcess && stopwatch.Elapsed.TotalSeconds < 5)
{
return;
}
try
{
InProcess = true;
stopwatch.Restart();
IoCheckProcess();
if (runStatus >= RunStatus.HomeMoving)
{
try
{
DateTime time = DateTime.Now;
if (MoveInfo.MoveType != LineMoveType.None)
{
if (MoveInfo.MoveType.Equals(LineMoveType.ReturnHome) || MoveInfo.MoveType.Equals(LineMoveType.StoreReset))
{
ResetProcess();
}
}
else if (runStatus.Equals(RunStatus.Runing))
{
InLineTimerProcess();
OutLineTimerProcess();
//TranverseTimerProcess();
IOTimeOutProcess();
SleepTimerProcess();
}
}
catch (Exception ex)
{
LogUtil.error(Name + "TimerProcess 定时处理出错", ex);
}
}
}
catch (Exception ex)
{
LogUtil.error(Name + "定时处理出错:" + ex.ToString());
}
InProcess = false;
}
private Stopwatch ol_noshelfWatch = new Stopwatch();
private DateTime ol_lastSendShelfTime = DateTime.Now;
private int StopDownMS = 1500;
/// <summary>
/// 出料线体定时处理
/// </summary>
private void OutLineTimerProcess()
{
TimeSpan span = DateTime.Now - ol_lastSendShelfTime;
//如果出口无料架,持续1000以上,放开阻挡放出一个料架
//每次放料架时间间隔3秒
if (IOManager.IOValue(IO_Type.StopCheck1).Equals(IO_VALUE.HIGH)&&IOManager.IOValue(IO_Type.OutCheck).Equals(IO_VALUE.LOW) && span.TotalSeconds > 3)
{
//如果入料线体出口无料架,放一个料架到出口
if (LineManager.checkWatch(ol_noshelfWatch, 1000))
{
LogUtil.info(" 线体出口无料架,下降 [" + IO_Type.StopDown + "] [" + StopDownMS + "] 秒");
ol_lastSendShelfTime = DateTime.Now;
StopIOMove(IO_Type.StopDown, StopDownMS);
}
}
else if (span.TotalMilliseconds > StopDownMS)
{
ol_noshelfWatch.Stop();
IOManager.CIOMove(IO_Type.StopDown, IO_VALUE.LOW);
}
TimeSpan span1 = DateTime.Now - il_lastCallAgvTime;
//出口有料架,需要通知agv取走料架
//每次叫小车时间间隔3分钟?
//出口信号需要持续1秒钟
if (IOManager.IOValue(IO_Type.OutCheck).Equals(IO_VALUE.HIGH) && span1.TotalSeconds > 60)
{
if (LastOutShelfId.Equals("000").Equals(false))
{
if (LineManager.checkWatch(il_outstopCheckWarch, 1000))
{
il_lastCallAgvTime = DateTime.Now;
LogUtil.info(" 出料线体出口有料架" + LastOutShelfId + ",呼叫agv小车[" + Config.Out_AgvName + "] [NeedLeave] ");
AgvClient.NeedLeave(Config.Out_AgvName, LastOutShelfId);
}
}
}
else if (span1.TotalMilliseconds > StopDownMS)
{
il_outstopCheckWarch.Stop();
ClientAction currA = AgvClient.GetAction(Config.Out_AgvName);
if (currA.Equals(ClientAction.None) || currA.Equals(ClientAction.NeedLeave) || currA.Equals(ClientAction.NeedEnter))
{
if (IOManager.IOValue(IO_Type.OutStopDown).Equals(IO_VALUE.HIGH))
{
IOManager.IOMove(IO_Type.OutStopDown, IO_VALUE.LOW);
}
}
}
//如果是出口无料架,NeedLeave状态,改为None
if (IOManager.IOValue(IO_Type.OutCheck).Equals(IO_VALUE.LOW) && AgvClient.GetAction(Config.Out_AgvName).Equals(ClientAction.NeedLeave))
{
il_outstopCheckWarch.Stop();
LogUtil.info(" 出料线体出口无料架 ,更改[" + Config.Out_AgvName + "] 状态[None] ");
AgvClient.SetToNone(Config.Out_AgvName);
}
}
private DateTime il_lastCallAgvTime = DateTime.Now.AddMinutes(-5);
private Stopwatch il_outstopCheckWarch = new Stopwatch();
/// <summary>
/// 入料线体定时处理
/// </summary>
private void InLineTimerProcess()
{
//如果入口无料架即可进入
if (IOManager.IOValue(IO_Type.InCheck).Equals(IO_VALUE.LOW))
{
AgvClient.NeedEnter(Config.In_AgvName, "");
}
else
{
AgvClient.SetToNone(Config.In_AgvName);
}
}
private Task TranverseTask;
private Stopwatch ol_tranverseShelfWatch = new Stopwatch();
private IO_VALUE LastResetValue = IO_VALUE.LOW;
public void IoCheckProcess()
{
DateTime time = DateTime.Now;
if (runStatus.Equals(RunStatus.Wait))
{
//取新的Io状态
IO_VALUE autoSingle = IOManager.IOValue(IO_Type.Reset_BTN);
if (ConfigAppSettings.GetIntValue(Setting_Init.App_AutoRun).Equals(1))
{
if (autoSingle.Equals(IO_VALUE.HIGH) && LastResetValue.Equals(IO_VALUE.LOW))
{
//没有启动时收到复位按钮,相当于启动按钮
LogUtil.info(Name + "没有启动时收到复位按钮,相当于启动按钮,开始调用启动方法!");
bool result = StartRun();
if (result.Equals(false))
{
LogUtil.error("VMI流水线启动失败,继续等待下次启动!");
mainTimer.Enabled = true;
}
}
LastResetValue = autoSingle;
return;
}
LastResetValue = autoSingle;
}
//判断急停
else if (runStatus >= RunStatus.HomeMoving)
{ //判断急停
if (IOManager.IOValue(IO_Type.SuddenStop_BTN).Equals(IO_VALUE.LOW))
{
if (isInSuddenDown.Equals(false))
{
isInSuddenDown = true;
SetWarnMsg("收到急停信号,报警急停");
//报警时会关闭所有轴
Alarm(AlarmType.SuddenStop);
}
}
else if (IOManager.IOValue(IO_Type.SuddenStop_BTN).Equals(IO_VALUE.HIGH) && IOManager.IOValue(IO_Type.Reset_BTN).Equals(IO_VALUE.HIGH))
{
//收到复位信号,若报警直接复位,若不报警且无操作,回到待机点
if (alarmType.Equals(AlarmType.None) && isInSuddenDown.Equals(false))
{
if (MoveInfo.MoveType.Equals(LineMoveType.None))
{
LogUtil.info("收到复位信号,当前无报警,暂不复位");
}
else
{
LogUtil.info("收到复位信号,当前无报警, 在" + MoveInfo.MoveType + "处理中,暂不复位");
}
}
else
{
//收到复位信号
LogUtil.info("收到复位信号,自动复位");
Reset();
}
}
}
}
private DateTime preIoTimerOutTime = DateTime.Now;
/// <summary>
/// io检测异常
/// </summary>
private void IOTimeOutProcess()
{
try
{
TimeSpan span = DateTime.Now - preIoTimerOutTime;
if (span.TotalSeconds > 1)
{
preIoTimerOutTime = DateTime.Now;
if (runStatus < RunStatus.Runing || isInSuddenDown)
{
return;
}
if (alarmType.Equals(AlarmType.IoSingleTimeOut) && MoveInfo.IsInWait == false)
{
LogUtil.info(Name + "之前有IO超时报警,清理报警:" + WarnMsg);
alarmType = AlarmType.None;
SetWarnMsg();
}
}
}
catch (Exception ex)
{
LogUtil.error(" IOTimeOutProcess 出错:" + ex.ToString());
}
}
#region 与服务器通信定时器,每1秒向服务器通知一次状态,同时执行出库操作
private string LastInShelfId = "";
public string LastOutShelfId = "B#";
private bool isInProcess = false;
public void server_connect_timer_Tick(object sender, EventArgs e)
{
if (isInProcess)
{
return;
}
isInProcess = true;
try
{
//LedProcess();
LastInShelfId = RFIDManager.ReadRFID(Config.L2_In_RFIDIP,true).NumStr();
LastOutShelfId = RFIDManager.ReadRFID(Config.L2_Out_RFIDIP,true).NumStr();
bool result = SendVmiRfid(LastInShelfId);
if (result)
{
IOManager.CIOMove(IO_Type.StopDown, IO_VALUE.HIGH);
}
else
{
IOManager.CIOMove(IO_Type.StopDown, IO_VALUE.LOW);
}
}
catch (Exception ex)
{
LogUtil.error(" server_connect_timer_Tick 出错:" + ex.ToString());
}
isInProcess = false;
}
private static string GetAddr(string addr, Dictionary<string, string> paramsMap)
{
string server = ConfigAppSettings.GetValue(Setting_Init.http_server);
if (server.EndsWith("/"))
{
server = server.Substring(0, server.Length - 1);
}
string path = server + addr.Trim() + "?";
foreach (string paramName in paramsMap.Keys)
{
string par = System.Web.HttpUtility.UrlEncode(paramsMap[paramName], System.Text.Encoding.UTF8);
path += paramName + "=" + par + "&";
}
path = path.Substring(0, path.Length - 1);
return path;
}
private string http_server = ConfigAppSettings.GetValue(Setting_Init.http_server);
private string api_communication = "/service/store/qisda/vmiRfid"; //流水线状态通信接口
private string lastLog = "";
public bool SendVmiRfid(string rfid)
{
try
{
Dictionary<string, string> paramMap = new Dictionary<string, string>();
paramMap.Add("rfid", rfid);
string addr = GetAddr(api_communication, paramMap ) ;
string resultStr = HttpHelper.Post(addr, "");
string log = "vmiRfid 【" + addr + "】【" + resultStr + "】";
if (lastLog.Equals(log).Equals(false))
{
lastLog = log;
LogUtil.info(log);
}
if (resultStr.Equals("move"))
{
return true;
}
}
catch (Exception ex)
{
LogUtil.error(Name + " " + ex.ToString());
}
return false;
}
#endregion
}
}
\ No newline at end of file \ No newline at end of file
using Asa;
using AsaPL;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
partial class LineBean
{
#region CheckWait处理
private DateTime preCheckAxisTime = DateTime.Now;
protected DateTime preRWTime = DateTime.Now;
internal void CheckWait(LineMoveInfo moveInfo)
{
try
{
List<WaitResultInfo> list = moveInfo.WaitList;
if (list.Count <= 0)
{
moveInfo.EndStepWait();
return;
}
//当等待超过一分钟时,需要打印提示
TimeSpan span = DateTime.Now - moveInfo.LastSetpTime;
string NotOkMsg = "";
bool isOk = true;
if (moveInfo.OneWaitCanEndStep)
{
isOk = false;
}
foreach (WaitResultInfo wait in list)
{
if (wait.IsEnd)
{
continue;
}
NotOkMsg = " [" + wait.ToStr() + "] ";
if (wait.WaitType.Equals(WaitEnum.W001_AxisMove))
{
}
else if (wait.WaitType.Equals(WaitEnum.W002_IOValue))
{
wait.IsEnd = IOManager.IOValue(wait.IoType).Equals(wait.IoValue);
}
else if (wait.WaitType.Equals(WaitEnum.W003_Time))
{
wait.IsEnd = (span.TotalMilliseconds >= wait.TimeMSeconds);
}
if (wait.IsEnd && moveInfo.OneWaitCanEndStep)
{
isOk = true;
break;
}
else if (!moveInfo.OneWaitCanEndStep)
{
isOk = false;
break;
}
}
if (isOk)
{
moveInfo.EndStepWait();
}
else if (span.TotalSeconds > moveInfo.TimeOutSeconds)
{
WarnMsg = Name + "[" + moveInfo.MoveType + "][" + moveInfo.MoveStep + "]等待" + NotOkMsg
+ "超时[" + Math.Round(span.TotalSeconds, 1) + "]秒";
LogUtil.error(WarnMsg);
Alarm(AlarmType.IoSingleTimeOut);
}
}
catch (Exception ex)
{
LogUtil.error(Name + " [" + moveInfo.MoveStep + "] CheckWait 出错:", ex);
}
}
public void StopIOMove(string ioType, int ms = 1000)
{
Task.Factory.StartNew(delegate
{
IOManager.IOMove(ioType, IO_VALUE.HIGH);
Thread.Sleep(ms);
IOManager.IOMove(ioType, IO_VALUE.LOW);
});
}
public void SetWarnMsg(string msg = "")
{
if (String.IsNullOrEmpty(msg).Equals(false))
{
if (WarnMsg.Equals(msg))
{
if (msg.StartsWith(Name))
{
LogUtil.error(msg, 105);
}
else
{
LogUtil.error(Name + msg, 105);
}
}
else
{
if (msg.StartsWith(Name))
{
LogUtil.error(msg);
}
else
{
LogUtil.error(Name + msg);
}
}
}
WarnMsg = msg;
}
public string GetRunInfo()
{
return "进料线入口" + Config.In_AgvName + ":" + AgvClient.GetAction(Config.In_AgvName) + ",料架: " + LastInShelfId + "\r\n" +
"出料线出口" + Config.Out_AgvName + ":" + AgvClient.GetAction(Config.Out_AgvName) + ",料架: " + LastOutShelfId + "\r\n";
}
#endregion
#region 休眠处理
public bool IsSleep = false;
private DateTime LastBusyTime = DateTime.Now;
private Dictionary<string, IO_VALUE> lastDIValue = new Dictionary<string, IO_VALUE>();
private List<string> needCheckList = new List<string>();
private int GetDIV(string type)
{
if (lastDIValue.ContainsKey(type))
{
return (int)lastDIValue[type];
}
return -1;
}
private void SleepTimerProcess()
{
if (needCheckList.Count <= 0)
{
needCheckList.Add(IO_Type.InCheck);
needCheckList.Add(IO_Type.StopCheck1);
needCheckList.Add(IO_Type.OutCheck);
needCheckList.Add(IO_Type.OutStopDown);
needCheckList.Add(IO_Type.StopDown);
}
bool agvBusy = false;
ClientAction currA = AgvClient.GetAction(Config.In_AgvName);
if (currA.Equals(ClientAction.None) || currA.Equals(ClientAction.NeedLeave) || currA.Equals(ClientAction.NeedEnter) )
{
ClientAction currB = AgvClient.GetAction(Config.Out_AgvName);
if (currB.Equals(ClientAction.None) || currB.Equals(ClientAction.NeedLeave) || currB.Equals(ClientAction.NeedEnter))
{
agvBusy = false;
}
else
{
LastBusyTime = DateTime.Now;
agvBusy = true;
}
}
else
{
LastBusyTime = DateTime.Now;
agvBusy = true;
}
if (agvBusy && IsSleep)
{
UpdateSleep(false);
return;
}
bool diIsBusy = false;
foreach (string type in needCheckList)
{
IO_VALUE currValue = IOManager.IOValue(type);
int lastValue = GetDIV(type);
if (((int)currValue).Equals(lastValue))
{
diIsBusy = false ;
}
else
{
if (lastDIValue.ContainsKey(type))
{
lastDIValue[type]=currValue;
}
else
{
lastDIValue.Add(type, currValue);
}
LastBusyTime = DateTime.Now;
diIsBusy = true;
UpdateSleep(false);
return;
}
}
if (diIsBusy.Equals(false) && agvBusy.Equals(false) && IsSleep.Equals(false))
{
TimeSpan time = DateTime.Now-LastBusyTime;
if (time.TotalSeconds > Config.SleepSeconds)
{
LogUtil.info(Name + "已经空闲【"+Math.Abs(time.TotalSeconds)+"】秒,开始休眠");
UpdateSleep(true);
}
}
}
public void UpdateSleep(bool needSleep)
{
if (needSleep)
{
IsSleep = true;
IOManager.IOMove(IO_Type.Line_Run, IO_VALUE.LOW);
}
else
{
IsSleep = false;
LastBusyTime = DateTime.Now;
IOManager.IOMove(IO_Type.Line_Run, IO_VALUE.HIGH);
};
}
#endregion
}
}
using log4net;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnlineStore.DeviceLibrary
{
public class LineManager
{
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static LineBean Line = null;
public static LineConfig Config = null;
private static bool isInit = false;
public static bool IsConnectServer = !ConfigAppSettings.GetValue(Setting_Init.http_server).Equals("");
public LineManager()
{
}
public static void CheckEnum(Type type)
{
if (type.IsEnum)
{
List<int> valueList = new List<int>();
foreach (int item in Enum.GetValues(type))
{
if (valueList.Contains(item))
{
LogUtil.error(LOGGER, type.Name + "枚举值:" + item + "重复存在,请检查代码!");
Application.Exit();
break;
}
valueList.Add(item);
}
}
}
public static LineBean InitStore()
{
try
{
RobotConfig.ProIOIpMap = new Dictionary<string, string>();
if (!isInit)
{
string server = ConfigAppSettings.GetValue(Setting_Init.http_server);
if (server.Equals(""))
{
IsConnectServer = false;
}
CheckEnum(typeof(MoveStep));
CheckEnum(typeof(RunStatus));
isInit = true;
string appPath = Application.StartupPath;
string linefilePath = appPath + ConfigAppSettings.GetValue(Setting_Init.Line_Config);
LogUtil.info(LOGGER, " 开始加载VMI流水线配置:" + linefilePath);
RobotConfig storeConfig = CSVConfigReader.LoadConfig(linefilePath);
Config = (LineConfig)storeConfig;
Line = new LineBean(Config);
LogUtil.info(LOGGER, "加载VMI流水线完成!");
return Line;
}
}
catch (Exception ex)
{
LOGGER.Error("出错:", ex);
MessageBox.Show(ex.ToString(), "加载配置错误(请检查配置)");
Application.Exit();
}
return Line;
}
public static bool checkWatch(Stopwatch watch, int targetMs, bool isStop = true)
{
if (!watch.IsRunning)
{
watch.Restart();
return false;
}
else if (watch.ElapsedMilliseconds >= targetMs)
{
watch.Stop();
return true;
}
return false;
}
public static string GetRunStr(RunStatus runs)
{
string sta = "运行中";
switch (runs)
{
case RunStatus.Busy:
sta = "忙碌";
break;
case RunStatus.HomeMoving:
sta = "原点返回";
break;
case RunStatus.Reset:
sta = "重置";
break;
case RunStatus.Runing:
sta = "运行中";
break;
case RunStatus.Wait:
sta = "等待启动";
break;
}
return sta;
}
}
}
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
public class WaitUtil
{
public delegate bool IsOk();
/// <summary>
/// 使用异步委托检测超时,防止isOk方法不返回结果导致卡死的问题
/// </summary>
/// <param name="waitName"></param>
/// <param name="timeout"></param>
/// <param name="isOk"></param>
public static bool Wait(int timeout, IsOk isOk, string waitName = "")
{
DateTime startTime = System.DateTime.Now;
TimeSpan timoutSpan = TimeSpan.FromMilliseconds(timeout);
TimeSpan waitSpan = TimeSpan.FromMilliseconds(0);
int sleepTime = 10;
while (true)
{
TimeSpan remainTimes = timoutSpan.Subtract(waitSpan);
if (remainTimes.TotalMilliseconds < 0)
{
//已经超时
throw new TimeoutException(waitName + "超时");
}
try
{
IAsyncResult re = isOk.BeginInvoke(null, null);
var waitResult = re.AsyncWaitHandle.WaitOne(remainTimes);
if (waitResult)
{
bool okResult = isOk.EndInvoke(re);
if (okResult)
{
return true;
}
}
}
catch (Exception ex)
{
LogUtil.error("同步等待出现异常:", ex);
}
Thread.Sleep(sleepTime);
waitSpan = System.DateTime.Now.Subtract(startTime);
}
}
}
}

using Asa;
using Asa.RFID;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace OnlineStore.DeviceLibrary
{
public class AgvClient
{
private static string ServerIp = ConfigAppSettings.GetValue(Setting_Init.AgvServerIp);
private static Asa.AgvClient agvClient;
public static Dictionary<string, Asa.ClientAction> actionMap = new Dictionary<string, Asa.ClientAction>();
public static List<string> NodeList = new List<string>();
private static bool isInit = false;
public static void Init()
{
try
{
if (!isInit)
{
isInit = true;
agvClient = new Asa.AgvClient(ServerIp);
agvClient.CancelState = true;
agvClient.Log += AgvClient_Log;
agvClient.Arrive += AgvClient_Arrive;
agvClient.Ready += AgvClient_Ready;
agvClient.CloseDoor += AgvClient_CloseDoor;
}
actionMap = new Dictionary<string, Asa.ClientAction>();
//foreach (string key in NodeList)
//{
// actionMap.Add(key, Asa.ClientAction.None);
//}
agvClient.Connect();
foreach (string str in NodeList)
{
SetStatus(str);
LogUtil.info("agv init ,SetStatus[" + str + "]=none ");
}
}
catch (Exception ex)
{
LogUtil.error("初始化agvClient " + ServerIp + " 出错:", ex);
}
}
public static void SetCancelState(bool isCancel)
{
agvClient.CancelState = isCancel;
}
private static void AgvClient_CloseDoor(string id, string rfid)
{
//RFIDData data = new RFIDData(content);
LogUtil.info("收到 AgvClient_CloseDoor [" + id + "] [" + rfid + "] ");
}
public static void SetStatus(string id, string shelfId = "", ClientAction action = ClientAction.None, ClientLevel level = ClientLevel.Low)
{
// ClientAction currA = GetAction(id);
if (actionMap.ContainsKey(id))
{
ClientAction currA = actionMap[id]; //相同状态就设置一次
if (currA.Equals(action))
{
return;
}
}
agvClient.SetStatus(id, "",shelfId, action, level);
UpdateAction(id, action);
}
private static void AgvClient_Ready(string id, string rfid)
{
// RFIDData data = new RFIDData(content);
string logName = "收到 AgvClient_Ready [" + id + "] [" + rfid + "] ";
LogUtil.info(logName);
UpdateAction(id, Asa.ClientAction.Ready);
if (id.Equals(LineManager.Config.L1_AgvName))
{
LineManager.VMILine.UpdateSleep(false);
if (IOManager.IOValue(IO_Type.L1_InCheck).Equals(IO_VALUE.LOW))
{
Task.Factory.StartNew(delegate
{
SetStatus(id, "", ClientAction.MayEnter);
LogUtil.info(logName + " ,等待L1_InCheck");
try
{
WaitUtil.Wait(60000, delegate
{
return IOManager.IOValue(IO_Type.L1_InCheck).Equals(IO_VALUE.HIGH);
}, "等待L1_InCheck=HIGH");
}
catch (Exception ex)
{
LogUtil.error(logName + ":" + ex.ToString());
}
//两秒后改为离开状态
Thread.Sleep(3000);
LogUtil.info(logName + " ,调用 FinishEnter ");
SetStatus(id, "", ClientAction.FinishEnter);
Thread.Sleep(5000);
LogUtil.info(logName + " ,处理结束 更新状态为None ");
SetStatus(id, "", ClientAction.None);
});
}
else
{
LogUtil.error(logName + " L1_InCheck 检测到有料架,AGV的料架无法进入");
SetStatus(id, "", ClientAction.None, ClientLevel.High);
}
}
else if (id.Equals(LineManager.Config.L2_AgvName))
{
string shefId = LineManager.VMILine.LastOutShelfId;
if (IOManager.IOValue(IO_Type.L2_OutCheck).Equals(IO_VALUE.HIGH))
{
SetStatus(id, shefId, ClientAction.MayLeave);
LineManager.VMILine.UpdateSleep(false);
LineManager.VMILine.StopIOMove(IO_Type.L2_OutStopDown, 1500);
//agvClient.MayLeave(id);
LogUtil.info(logName + "下降 L2_OutStopDown , " + shefId);
Task.Factory.StartNew(delegate
{
//两秒后改为离开状态
Thread.Sleep(5000);
LogUtil.info(logName + " ,调用 FinishLeave " + shefId);
SetStatus(id, shefId, ClientAction.FinishLeave);
Thread.Sleep(5000);
LogUtil.info(logName + " ,处理结束 更新状态为None ");
SetStatus(id, "", ClientAction.None);
});
}
else
{
LogUtil.error(logName + " L2_OutCheck 未检测到料架,无法将料架进入AGV");
SetStatus(id, "", ClientAction.None, ClientLevel.High);
}
}
}
private static void AgvClient_Arrive(string id, string rfid)
{
UpdateAction(id, Asa.ClientAction.Arrive);
// RFIDData data = new RFIDData(content);
LogUtil.info("收到 AgvClient_Arrive [" + id + "] [" +rfid + "] ");
}
public static bool SetToNone(string id, string shelfId = "")
{
ClientAction currA = GetAction(id);
if (currA.Equals(ClientAction.None) || currA.Equals(ClientAction.NeedLeave) || currA.Equals(ClientAction.NeedEnter))
{
SetStatus(id, shelfId, ClientAction.None);
return true;
}
return false;
}
public static bool NeedEnter(string id, string shelfId)
{
ClientAction currA = GetAction(id);
if (currA.Equals(ClientAction.None) || currA.Equals(ClientAction.NeedLeave) || currA.Equals(ClientAction.NeedEnter))
{
SetStatus(id, shelfId, ClientAction.NeedEnter);
return true;
}
return false;
}
public static bool NeedLeave(string id, string shelfId)
{
ClientAction currA = GetAction(id);
if (currA.Equals(ClientAction.None) || currA.Equals(ClientAction.NeedLeave) || currA.Equals(ClientAction.NeedEnter))
{
SetStatus(id, shelfId, ClientAction.NeedLeave);
return true;
}
return false;
}
public static bool ISConnected()
{
if (agvClient == null)
{
return false;
}
return agvClient.IsConn;
}
//public static void SendRFID(string NodeName, string rfid)
//{
// agvClient.SendRFID(NodeName, rfid);
//}
private static void AgvClient_Log(string s)
{
try
{
bool isLog = ConfigAppSettings.GetIntValue(Setting_Init.Agv_Log_Open).Equals(1);
if (isLog)
{
LogUtil.info(" AGV " + ServerIp + " Log : " + s);
}
}
catch (Exception ex)
{
LogUtil.error("AgvClient_Log 出错:" + ex.ToString());
}
}
public static Asa.ClientAction GetAction(string NodeName)
{
if (actionMap.ContainsKey(NodeName))
{
return actionMap[NodeName];
}
return Asa.ClientAction.None;
}
public static void UpdateAction(string name, Asa.ClientAction action)
{
if (actionMap.ContainsKey(name))
{
actionMap[name] = action;
}
else
{
actionMap.Add(name, action);
}
}
public static void Dispose()
{
try
{
if (agvClient != null)
{
agvClient.Close();
}
}
catch (Exception ex)
{
LogUtil.error("agvClient.Close " + ServerIp + " 出错:", ex);
}
}
}
}

using OnlineStore.Common;
using System;
using System.Collections.Generic;
using AsaPL;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OnlineStore.LoadCSVLibrary;
namespace OnlineStore.DeviceLibrary
{
public class AgvClient_Line
{
private static string ServerIp = ConfigAppSettings.GetValue(Setting_Init.AgvServerIp);
public AsaPL.AgvClient agvClient;
private static bool isInit = false;
public static Dictionary<string, AsaPL.ClientAction> actionMap = new Dictionary<string, AsaPL.ClientAction>();
string Agv_In_Name = "A2";
string Agv_Out_Name = "A1";
public void Init(string agvIn,string agvOut)
{
try
{
if (!isInit)
{
isInit = true;
agvClient = new AsaPL.AgvClient(ServerIp);
agvClient.CancelState = false;
agvClient.ReadyEnter += AgvClient_ReadyEnter;
agvClient.ReadyLeave += AgvClient_ReadyLeave;
agvClient.AGVFinishEnter += AgvClient_FinishEnter;
agvClient.AGVFinishLeave += AgvClient_FinishLeave;
}
actionMap = new Dictionary<string, AsaPL.ClientAction>();
Agv_In_Name = agvIn;
Agv_Out_Name = agvOut;
agvClient.SetStatus(Agv_In_Name, "", ClientAction.None);
agvClient.SetStatus(Agv_Out_Name, "", ClientAction.None);
agvClient.Connect();
LogUtil.info("初始化AGV服务");
}
catch (Exception ex)
{
LogUtil.error("初始化AGV服务 " + ServerIp + " 出错:", ex);
}
}
/// <summary>
/// 设置取消状态
/// </summary>
/// <param name="isCancel">true则ClientAction为None</param>
public void SetCancelState(bool isCancel)
{
agvClient.CancelState = isCancel;
}
/// <summary>
/// 料架准备进入线体
/// </summary>
/// <param name="name">节点名称</param>
private void AgvClient_ReadyEnter(string name)
{
LogUtil.info("收到 AgvClient_ReadyEnter [" + name + "]");
if (name.Equals(Agv_In_Name))
{
LineManager.Line.UpdateSleep(false);
if (IOManager.IOValue(IO_Type.InCheck).Equals(IO_VALUE.LOW))
{
Task.Factory.StartNew(delegate
{
SetStatus(name, "", ClientAction.MayEnter);
LogUtil.info("入口无料架,向服务端发送 MayEnter");
try
{
WaitUtil.Wait(60000, delegate
{
return IOManager.IOValue(IO_Type.InCheck).Equals(IO_VALUE.HIGH);
}, "等待InCheck=HIGH");
}
catch (Exception ex)
{
LogUtil.error("AgvClient_ReadyEnter:" + ex.ToString());
}
//两秒后改为离开状态
Thread.Sleep(3000);
LogUtil.info("调用 FinishEnter ");
SetStatus(name, "", ClientAction.FinishEnter);
Thread.Sleep(5000);
LogUtil.info( "处理结束 更新状态为None ");
SetStatus(name, "", ClientAction.None);
});
}
else
{
LogUtil.error("InCheck 检测到有料架,AGV的料架无法进入");
SetStatus(name, "", ClientAction.None, ClientLevel.High);
}
}
}
/// <summary>
///料架准备离开线体
/// </summary>
/// <param name="name">节点名称</param>
private void AgvClient_ReadyLeave(string name)
{
LogUtil.info("收到 AgvClient_ReadyLeave [" + name + "] ");
if (name.Equals(Agv_Out_Name))
{
if (IOManager.IOValue(IO_Type.OutCheck).Equals(IO_VALUE.HIGH))
{
SetStatus(name, "", ClientAction.MayLeave);
Thread.Sleep(3000);
LineManager.Line.UpdateSleep(false);
LineManager.Line.StopIOMove(IO_Type.OutStopDown, 1500);
LogUtil.info("下降 OutStopDown1.5秒");
Task.Factory.StartNew(delegate
{
//两秒后改为离开状态
Thread.Sleep(5000);
LogUtil.info("调用 FinishLeave ");
SetStatus(name, "", ClientAction.FinishLeave);
Thread.Sleep(5000);
LogUtil.info("处理结束 更新状态为None ");
SetStatus(name, "", ClientAction.None);
});
}
else
{
LogUtil.error("OutCheck 未检测到料架,无法将料架进入AGV");
SetStatus(name, "", ClientAction.None, ClientLevel.High);
}
}
}
/// <summary>
/// 料架离开小车完成
/// </summary>
/// <param name="name"></param>
private void AgvClient_FinishLeave(string name)
{
LogUtil.info("收到 AgvClient_FinishLeave [" + name + "] ");
}
/// <summary>
/// 料架进入小车完成
/// </summary>
/// <param name="name"></param>
private void AgvClient_FinishEnter(string name)
{
LogUtil.info("收到 AgvClient_FinishEnter [" + name + "] ");
}
/// <summary>
/// 左侧料架可以进入
/// </summary>
public bool A5_ReadyEnter { private set; get; }
/// <summary>
/// 右侧料架可以进入
/// </summary>
public bool A6_ReadyEnter { private set; get; }
/// <summary>
/// 右侧料架可以出去
/// </summary>
public bool A6_ReadyLeave { private set; get; }
public void MayEnter(string name)
{
SetStatus(name, "", ClientAction.MayEnter);
if (name.Equals("A5"))
{
A5_ReadyEnter = false;
}
else if (name.Equals("A6"))
{
A6_ReadyEnter = false;
}
}
public void MayLeave(string name)
{
SetStatus(name, "", ClientAction.MayLeave);
if (name.Equals("A6"))
{
A6_ReadyLeave = false;
}
}
public void NeedEnter(string nodeName,string rfid)
{
SetStatus(nodeName, rfid,ClientAction.NeedEnter);
}
public void NeedLeave(string nodeName, string rfid)
{
SetStatus(nodeName, rfid,ClientAction.NeedLeave);
}
public void SetToNone(string nodeName)
{
SetStatus(nodeName);
}
private bool SetStatus(string name, string shelfId = "", ClientAction action = ClientAction.None, ClientLevel level = ClientLevel.Low)
{
// if (!agvClient.IsConn)
// {
// LogUtil.error("SetStatus AGV服务未连接!");
// return false;
// }
if (actionMap.ContainsKey(name))
{
//ClientAction currA = actionMap[name]; //相同状态就设置一次
//if (currA.Equals(action) && shelfId == "")
//{
// return false;
//}
actionMap[name] = action;
agvClient.SetStatus(name, shelfId, action, level);
//LogUtil.info("设置 " + name + " [" + shelfId + "] " + action.ToString());
return true;
}
agvClient.SetStatus(name, shelfId, action, level);
actionMap.Add(name, action);
LogUtil.debug("设置 " + name + " ["+ shelfId + "] "+ action.ToString());
return true;
}
public bool ISConnected()
{
if (agvClient == null)
{
return false;
}
return agvClient.IsConn;
}
public void Dispose()
{
try
{
if (agvClient != null)
{
agvClient.Close();
LogUtil.info("关闭AGV服务");
}
}
catch (Exception ex)
{
LogUtil.error("关闭AGV服务 " + ServerIp + " 出错:", ex);
}
}
public ClientAction GetAction(string NodeName)
{
if (actionMap.ContainsKey(NodeName))
{
return actionMap[NodeName];
}
return ClientAction.None;
}
}
}
using OnlineStore.Common;
using OnlineStore.DeviceLibrary;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.DeviceLibrary
{
/// <summary>
/// VMI流水线当前运动信息类(出入库状态,步骤记录)
/// </summary>
public class LineMoveInfo
{
/// <summary>
/// 超时时间
/// </summary>
public int TimeOutSeconds = 60;
public LineMoveInfo( )
{
moveType = LineMoveType.None;
this.moveStep = MoveStep.Wait;
IsInWait = false;
}
public DateTime LastSetpTime { get; set; }
/// <summary>
/// =true表示满足一个等待条件,就可以完成此步骤的等待
/// </summary>
public bool OneWaitCanEndStep = false;
/// <summary>
/// 操作类型
/// </summary>
private LineMoveType moveType = LineMoveType.None;
public LineMoveType MoveType
{
get { return moveType; }
}
/// <summary>
/// 是否再当前步骤等待中
/// </summary>
public bool IsInWait { get; set; }
/// <summary>
/// 上一个执行步骤
/// </summary>
public MoveStep PreMoveStep { get; set; }
/// <summary>
/// 当前执行到的步骤
/// </summary>
private MoveStep moveStep;
/// <summary>
/// 可以循环运动的次数(轴卡运动才需要)
/// </summary>
public int CanWhileCount = 0;
/// <summary>
/// VMI流水线运动步骤记录
/// </summary>
public MoveStep MoveStep
{
get { return moveStep; }
}
public void NextMoveStep(MoveStep step)
{
PreMoveStep = moveStep;
moveStep = step;
LastSetpTime = DateTime.Now;
IsInWait = true;
WaitList = new List<WaitResultInfo>();
OneWaitCanEndStep = false;
CanWhileCount = 5;
TimeOutSeconds = 60;
}
/// <summary>
/// 当前步骤执行完成
/// </summary>
public void EndStepWait()
{
IsInWait = false;
WaitList = new List<WaitResultInfo>();
}
public void NewMove(LineMoveType type )
{
moveStep = MoveStep.Wait;
this.moveType = type;
LastSetpTime = DateTime.Now;
WaitList = new List<WaitResultInfo>();
}
public void EndMove()
{
this.moveType = LineMoveType.None;
// this.MoveParam = null;
moveStep = MoveStep.Wait;
LastSetpTime = DateTime.Now;
IsInWait = false;
WaitList = new List<WaitResultInfo>();
CanWhileCount = 0;
}
public LineMoveInfo clone()
{
return (LineMoveInfo)this.MemberwiseClone();
}
public List<WaitResultInfo> WaitList = new List<WaitResultInfo>();
/// <summary>
/// 重置之后继续出入库时,退回上一个步骤执行
/// </summary>
public void BackStep()
{
moveStep = PreMoveStep;
IsInWait = false;
}
}
public class WaitResultInfo
{
private WaitResultInfo()
{
}
public static WaitResultInfo WaitIO(string ioType, IO_VALUE ioValue)
{
WaitResultInfo wait = new WaitResultInfo();
wait.CanWhileMoveCount = 0;
wait.WaitType = 2;
wait.IoType = ioType;
wait.IoValue = ioValue;
wait.IsEnd = false;
return wait;
}
public static WaitResultInfo WaitTime(int MScends)
{
WaitResultInfo wait = new WaitResultInfo();
wait.CanWhileMoveCount = 0;
wait.WaitType = 3;
wait.TimeMSeconds = MScends;
wait.IsEnd = false;
return wait;
}
public string ToStr()
{
if (WaitType == 1)
{
}
else if (WaitType == 2)
{
return "IO信号等待,IO类型【" + IoType + "】,等待值【" + IoValue + "】";
}
else if (WaitType == 3)
{
return "时间等待:【" + TimeMSeconds + "】毫秒";
}
else
{
return "Wait位置类型:WaitType=【" + WaitType + "】";
}
return "";
}
/// <summary>
/// 当未结束时可以重复运动的次数
/// </summary>
public int CanWhileMoveCount { get; set; }
/// <summary>
/// 等待结果,1=轴运动,2=IO运动,3=时间,4=电钢,5=硕科电机,6=等待轴原点信号
/// </summary>
public int WaitType { get; set; }
/// <summary>
/// IO类型
/// </summary>
public String IoType { get; set; }
/// <summary>
/// IO值
/// </summary>
public IO_VALUE IoValue { get; set; }
/// <summary>
/// 等待的毫秒
/// </summary>
public int TimeMSeconds { get; set; }
/// <summary>
/// 是否已经结束
/// </summary>
public bool IsEnd{ get; set; }
}
internal class WaitEnum
{
/// <summary>
/// 伺服运动
/// </summary>
internal static int W001_AxisMove = 1;
/// <summary>
/// 信号到达
/// </summary>
internal static int W002_IOValue = 2;
/// <summary>
/// 时间等待
/// </summary>
internal static int W003_Time = 3;
/// <summary>
/// 电钢运动
/// </summary>
internal static int W004_StellMove = 4;
/// <summary>
/// 硕科电机
/// </summary>
internal static int W005_ShuoKe = 5;
/// <summary>
/// 轴原点信号
/// </summary>
internal static int W006_AxisOrg = 6;
}
public enum LineMoveType
{
/// <summary>
/// 没有任何操作
/// </summary>
None = 0,
/// <summary>
/// 入库
/// </summary>
InStore = 1,
/// <summary>
/// 出库
/// </summary>
OutStore = 2,
/// <summary>
/// 原点返回
/// </summary>
ReturnHome = 3,
/// <summary>
/// 重置
/// </summary>
StoreReset = 4,
}
}
using log4net;
using OnlineStore.Common;
using OnlineStore.DeviceLibrary;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnlineStore.DeviceLibrary
{
/// <summary>
/// 等待启动/已经停止,初始化完成, 正常运行中,可以进行新的处理,忙碌,重置
/// </summary>
public enum RunStatus
{
/// <summary>
/// 等待启动/已经停止
/// </summary>
Wait = 0,
/// <summary>
/// 初始化 ,原点返回状态中
/// </summary>
HomeMoving = 1,
/// <summary>
/// 设备正在重置中,请稍后
/// </summary>
Reset = 2,
/// <summary>
/// 正常运行中,可以进行新的处理
/// </summary>
Runing = 3,
/// <summary>
/// 正在忙碌中,请稍后
/// </summary>
Busy = 4,
}
public enum MoveStep
{
/// <summary>
/// 无操作,等待状态
/// </summary>
Wait = 0,
#region VMI流水线原点返回和重置步骤
/// <summary>
/// VMI流水线复位:所有阻挡上升
/// </summary>
VMI_H_StopUp=010,
/// <summary>
/// VMI流水线复位:线体开始转动
/// </summary>
VMI_H_LineRun = 011,
#endregion
}
public enum AlarmType
{
/// <summary>
/// 没有报警
/// </summary>
None = 0,
///// <summary>
///// 轴报警
///// </summary>
//AxisAlarm = 1,
/// <summary>
/// 收到急停
/// </summary>
SuddenStop = 10,
///// <summary>
///// 没有气压信号
///// </summary>
//NoAirCheck = 11,
///// <summary>
///// 轴运动错误,没有达到指定脉冲,但是io判断已停止运动
///// </summary>
//AxisMoveError = 20,
/// <summary>
/// io信号超时未收到
/// </summary>
IoSingleTimeOut = 30,
///// <summary>
///// 电钢报警
///// </summary>
//StellAlarm=50,
}
}
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<appSettings>
<!--是否开机自动启动VMI流水线-->
<add key="App_AutoRun" value="1" />
<add key="App_Title" value="空料架缓存线" />
<!--Server address-->
<add key="http.server" value="http://10.85.162.124/myproject/" />
<!--storeType-->
<add key="store_count" value="1" />
<!--start one store config-->
<add key="Line_Config" value="\LineConfig\LineConfig.csv" />
<add key="Config_Pwd" value="123456" />
<!--IO配置-->
<add key="UseAIOBOX" value="1" />
<add key="DIMS" value="60" />
<add key="DOMS" value="300" />
<!--AGV调度服务器地址-->
<add key="AgvServerIp" value="127.0.0.1" />
<!--是否调试状态-->
<add key="IsInDebug" value="1" />
<add key ="Agv_Log_Open" value ="1"/>
</appSettings>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="logs/vmiLine.log" />
<param name="Encoding" value="UTF-8" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date][%t]%-5p %m%n" />
</layout>
</appender>
<appender name="TheRFID" type="log4net.Appender.RollingFileAppender">
<file value="logs/TheRFID-vmi.log"/>
<param name="Encoding" value="UTF-8" />
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="yyyy-MM-dd"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date][%t]%-5p %m%n" />
</layout>
</appender>
<logger name="RollingLogFileAppender">
<level value="Info" />
<appender-ref ref="RollingLogFileAppender" />
</logger>
<logger name="TheRFID">
<level value="Error" />
<appender-ref ref="TheRFID" />
</logger>
<root>
<level value="Info" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
</configuration>
\ No newline at end of file \ No newline at end of file
此文件类型无法预览
此文件类型无法预览
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0D2542F5-DD62-4352-82D0-383D9A045E74}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OnlineStore.ACSingleStore</RootNamespace>
<AssemblyName>EmptyShelfLine</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>DfIcon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Client, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\dll\Client.dll</HintPath>
</Reference>
<Reference Include="log4net">
<HintPath>..\..\dll\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FrmBase.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmBase.Designer.cs">
<DependentUpon>FrmBase.cs</DependentUpon>
</Compile>
<Compile Include="FrmLineClient.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmLineClient.Designer.cs">
<DependentUpon>FrmLineClient.cs</DependentUpon>
</Compile>
<Compile Include="ManagerUtil.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="FrmBase.resx">
<DependentUpon>FrmBase.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FrmLineClient.resx">
<DependentUpon>FrmLineClient.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj">
<Project>{43cdd09e-fcf3-4960-a01d-3bbfe9933122}</Project>
<Name>Common</Name>
</ProjectReference>
<ProjectReference Include="..\DeviceLibrary\DeviceLibrary.csproj">
<Project>{513bc1c9-800d-43a6-9499-3700baec3554}</Project>
<Name>DeviceLibrary</Name>
</ProjectReference>
<ProjectReference Include="..\LoadCVSLibrary\LoadCSVLibrary.csproj">
<Project>{064bebf5-8faa-4ea2-a5f3-a06e6e7d9251}</Project>
<Name>LoadCSVLibrary</Name>
</ProjectReference>
<ProjectReference Include="..\UserFromControl\UserFromControl.csproj">
<Project>{f018462a-d9bc-4365-97f2-f6d71751641e}</Project>
<Name>UserFromControl</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="AuToRunManager.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="DfIcon.ico" />
<Content Include="记录.txt" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file \ No newline at end of file
namespace OnlineStore.VMILineClient
{
partial class FrmBase
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmBase));
this.SuspendLayout();
//
// FrmBase
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(300, 300);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "FrmBase";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "FrmBase";
this.ResumeLayout(false);
}
#endregion
}
}
\ No newline at end of file \ No newline at end of file
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OnlineStore.VMILineClient
{
public partial class FrmBase : Form
{
public FrmBase()
{
InitializeComponent();
}
}
}
此文件的差异太大,无法显示。
namespace OnlineStore.VMILineClient
{
partial class FrmVMIClient
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmVMIClient));
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.显示ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox5 = new System.Windows.Forms.GroupBox();
this.btnNone = new System.Windows.Forms.Button();
this.txtShelfId = new System.Windows.Forms.TextBox();
this.txtname = new System.Windows.Forms.TextBox();
this.btnNeedEnter = new System.Windows.Forms.Button();
this.btnNeedLeave = new System.Windows.Forms.Button();
this.btnDis = new System.Windows.Forms.Button();
this.btnInit = new System.Windows.Forms.Button();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.btnStopTDown = new System.Windows.Forms.Button();
this.cmbStopList = new System.Windows.Forms.ComboBox();
this.btnCloseA = new System.Windows.Forms.Button();
this.btnClearL = new System.Windows.Forms.Button();
this.btnLogDebug = new System.Windows.Forms.Button();
this.btnInLOutStopDown = new System.Windows.Forms.Button();
this.btnInLInStopDown = new System.Windows.Forms.Button();
this.btnInLineRun = new System.Windows.Forms.Button();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.lblWarnMsg = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel();
this.chbMoveStop = new System.Windows.Forms.CheckBox();
this.lblInfo = new System.Windows.Forms.Label();
this.btnVmiExit = new System.Windows.Forms.Button();
this.btnVmiStart = new System.Windows.Forms.Button();
this.chbDebug = new System.Windows.Forms.CheckBox();
this.btnVmiStop = new System.Windows.Forms.Button();
this.chbAuto = new System.Windows.Forms.CheckBox();
this.lblThisSta = new System.Windows.Forms.Label();
this.contextMenuStrip1.SuspendLayout();
this.groupBox5.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.groupBox4.SuspendLayout();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// timer1
//
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// notifyIcon1
//
this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1;
this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
this.notifyIcon1.Text = "VMI流水线客户端";
this.notifyIcon1.Visible = true;
//
// contextMenuStrip1
//
this.contextMenuStrip1.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.显示ToolStripMenuItem,
this.toolStripSeparator8,
this.toolStripMenuItem1});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(113, 62);
//
// 显示ToolStripMenuItem
//
this.显示ToolStripMenuItem.Name = "显示ToolStripMenuItem";
this.显示ToolStripMenuItem.Size = new System.Drawing.Size(112, 26);
this.显示ToolStripMenuItem.Text = "显示";
this.显示ToolStripMenuItem.Click += new System.EventHandler(this.显示ToolStripMenuItem_Click);
//
// toolStripSeparator8
//
this.toolStripSeparator8.Name = "toolStripSeparator8";
this.toolStripSeparator8.Size = new System.Drawing.Size(109, 6);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(112, 26);
this.toolStripMenuItem1.Text = "退出";
this.toolStripMenuItem1.Click += new System.EventHandler(this.退出ToolStripMenuItem_Click);
//
// groupBox5
//
this.groupBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox5.Controls.Add(this.btnNone);
this.groupBox5.Controls.Add(this.txtShelfId);
this.groupBox5.Controls.Add(this.txtname);
this.groupBox5.Controls.Add(this.btnNeedEnter);
this.groupBox5.Controls.Add(this.btnNeedLeave);
this.groupBox5.Controls.Add(this.btnDis);
this.groupBox5.Controls.Add(this.btnInit);
this.groupBox5.Location = new System.Drawing.Point(450, 132);
this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(728, 77);
this.groupBox5.TabIndex = 277;
this.groupBox5.TabStop = false;
this.groupBox5.Text = "AGV调度通信";
//
// btnNone
//
this.btnNone.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnNone.Location = new System.Drawing.Point(577, 24);
this.btnNone.Name = "btnNone";
this.btnNone.Size = new System.Drawing.Size(100, 39);
this.btnNone.TabIndex = 7;
this.btnNone.Text = "None";
this.btnNone.UseVisualStyleBackColor = true;
this.btnNone.Click += new System.EventHandler(this.btnNone_Click);
//
// txtShelfId
//
this.txtShelfId.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.txtShelfId.Location = new System.Drawing.Point(300, 31);
this.txtShelfId.MaxLength = 4;
this.txtShelfId.Name = "txtShelfId";
this.txtShelfId.Size = new System.Drawing.Size(53, 26);
this.txtShelfId.TabIndex = 6;
this.txtShelfId.Text = "000";
//
// txtname
//
this.txtname.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.txtname.Location = new System.Drawing.Point(239, 31);
this.txtname.MaxLength = 4;
this.txtname.Name = "txtname";
this.txtname.Size = new System.Drawing.Size(53, 26);
this.txtname.TabIndex = 5;
this.txtname.Text = "C2";
//
// btnNeedEnter
//
this.btnNeedEnter.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnNeedEnter.Location = new System.Drawing.Point(469, 24);
this.btnNeedEnter.Name = "btnNeedEnter";
this.btnNeedEnter.Size = new System.Drawing.Size(100, 39);
this.btnNeedEnter.TabIndex = 4;
this.btnNeedEnter.Text = "NeedEntry";
this.btnNeedEnter.UseVisualStyleBackColor = true;
this.btnNeedEnter.Click += new System.EventHandler(this.btnNeedEntry_Click);
//
// btnNeedLeave
//
this.btnNeedLeave.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnNeedLeave.Location = new System.Drawing.Point(361, 24);
this.btnNeedLeave.Name = "btnNeedLeave";
this.btnNeedLeave.Size = new System.Drawing.Size(100, 39);
this.btnNeedLeave.TabIndex = 3;
this.btnNeedLeave.Text = "NeedLeave";
this.btnNeedLeave.UseVisualStyleBackColor = true;
this.btnNeedLeave.Click += new System.EventHandler(this.btnNeedLeave_Click);
//
// btnDis
//
this.btnDis.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDis.Location = new System.Drawing.Point(131, 24);
this.btnDis.Name = "btnDis";
this.btnDis.Size = new System.Drawing.Size(100, 39);
this.btnDis.TabIndex = 2;
this.btnDis.Text = "断开";
this.btnDis.UseVisualStyleBackColor = true;
this.btnDis.Click += new System.EventHandler(this.btnDis_Click);
//
// btnInit
//
this.btnInit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnInit.Location = new System.Drawing.Point(23, 24);
this.btnInit.Name = "btnInit";
this.btnInit.Size = new System.Drawing.Size(100, 39);
this.btnInit.TabIndex = 1;
this.btnInit.Text = "连接";
this.btnInit.UseVisualStyleBackColor = true;
this.btnInit.Click += new System.EventHandler(this.btnInit_Click);
//
// groupBox2
//
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.numericUpDown1);
this.groupBox2.Controls.Add(this.btnStopTDown);
this.groupBox2.Controls.Add(this.cmbStopList);
this.groupBox2.Controls.Add(this.btnCloseA);
this.groupBox2.Controls.Add(this.btnClearL);
this.groupBox2.Controls.Add(this.btnLogDebug);
this.groupBox2.Controls.Add(this.btnInLOutStopDown);
this.groupBox2.Controls.Add(this.btnInLInStopDown);
this.groupBox2.Controls.Add(this.btnInLineRun);
this.groupBox2.Controls.Add(this.groupBox4);
this.groupBox2.Controls.Add(this.groupBox1);
this.groupBox2.Location = new System.Drawing.Point(10, 132);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(434, 551);
this.groupBox2.TabIndex = 276;
this.groupBox2.TabStop = false;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(248, 441);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(25, 17);
this.label1.TabIndex = 286;
this.label1.Text = "ms";
//
// numericUpDown1
//
this.numericUpDown1.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.numericUpDown1.Increment = new decimal(new int[] {
50,
0,
0,
0});
this.numericUpDown1.Location = new System.Drawing.Point(181, 436);
this.numericUpDown1.Maximum = new decimal(new int[] {
300000,
0,
0,
0});
this.numericUpDown1.Minimum = new decimal(new int[] {
100,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(61, 26);
this.numericUpDown1.TabIndex = 285;
this.numericUpDown1.Value = new decimal(new int[] {
600,
0,
0,
0});
//
// btnStopTDown
//
this.btnStopTDown.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnStopTDown.Location = new System.Drawing.Point(279, 430);
this.btnStopTDown.Name = "btnStopTDown";
this.btnStopTDown.Size = new System.Drawing.Size(127, 39);
this.btnStopTDown.TabIndex = 284;
this.btnStopTDown.Text = "阻挡定时下降";
this.btnStopTDown.UseVisualStyleBackColor = true;
this.btnStopTDown.Click += new System.EventHandler(this.btnStopTDown_Click);
//
// cmbStopList
//
this.cmbStopList.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbStopList.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.cmbStopList.FormattingEnabled = true;
this.cmbStopList.Items.AddRange(new object[] {
"线体阻挡",
"线体出口阻挡"});
this.cmbStopList.Location = new System.Drawing.Point(22, 435);
this.cmbStopList.Name = "cmbStopList";
this.cmbStopList.Size = new System.Drawing.Size(153, 28);
this.cmbStopList.TabIndex = 283;
//
// btnCloseA
//
this.btnCloseA.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnCloseA.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnCloseA.Location = new System.Drawing.Point(22, 495);
this.btnCloseA.Name = "btnCloseA";
this.btnCloseA.Size = new System.Drawing.Size(173, 39);
this.btnCloseA.TabIndex = 282;
this.btnCloseA.Text = "关闭所有DO";
this.btnCloseA.UseVisualStyleBackColor = true;
this.btnCloseA.Click += new System.EventHandler(this.btnCloseA_Click);
//
// btnClearL
//
this.btnClearL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnClearL.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClearL.Location = new System.Drawing.Point(301, 495);
this.btnClearL.Name = "btnClearL";
this.btnClearL.Size = new System.Drawing.Size(104, 39);
this.btnClearL.TabIndex = 14;
this.btnClearL.Text = "清理日志";
this.btnClearL.UseVisualStyleBackColor = true;
this.btnClearL.Click += new System.EventHandler(this.btnClearL_Click);
//
// btnLogDebug
//
this.btnLogDebug.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnLogDebug.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnLogDebug.Location = new System.Drawing.Point(196, 495);
this.btnLogDebug.Name = "btnLogDebug";
this.btnLogDebug.Size = new System.Drawing.Size(104, 39);
this.btnLogDebug.TabIndex = 13;
this.btnLogDebug.Text = "开启DEBUG";
this.btnLogDebug.UseVisualStyleBackColor = true;
this.btnLogDebug.Click += new System.EventHandler(this.btnLogDebug_Click);
//
// btnInLOutStopDown
//
this.btnInLOutStopDown.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnInLOutStopDown.Location = new System.Drawing.Point(316, 279);
this.btnInLOutStopDown.Name = "btnInLOutStopDown";
this.btnInLOutStopDown.Size = new System.Drawing.Size(107, 39);
this.btnInLOutStopDown.TabIndex = 279;
this.btnInLOutStopDown.Text = "出口阻挡下降";
this.btnInLOutStopDown.UseVisualStyleBackColor = true;
this.btnInLOutStopDown.Click += new System.EventHandler(this.btnInLOutStopDown_Click);
//
// btnInLInStopDown
//
this.btnInLInStopDown.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnInLInStopDown.Location = new System.Drawing.Point(166, 279);
this.btnInLInStopDown.Name = "btnInLInStopDown";
this.btnInLInStopDown.Size = new System.Drawing.Size(107, 39);
this.btnInLInStopDown.TabIndex = 278;
this.btnInLInStopDown.Text = "阻挡下降";
this.btnInLInStopDown.UseVisualStyleBackColor = true;
this.btnInLInStopDown.Click += new System.EventHandler(this.btnInLInStopDown_Click);
//
// btnInLineRun
//
this.btnInLineRun.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnInLineRun.Location = new System.Drawing.Point(9, 279);
this.btnInLineRun.Name = "btnInLineRun";
this.btnInLineRun.Size = new System.Drawing.Size(107, 39);
this.btnInLineRun.TabIndex = 276;
this.btnInLineRun.Text = "线体运转";
this.btnInLineRun.UseVisualStyleBackColor = true;
this.btnInLineRun.Click += new System.EventHandler(this.btnInLineRun_Click);
//
// groupBox4
//
this.groupBox4.Controls.Add(this.tableLayoutPanel2);
this.groupBox4.Location = new System.Drawing.Point(218, 15);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(208, 251);
this.groupBox4.TabIndex = 275;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "DO列表";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.AutoScroll = true;
this.tableLayoutPanel2.ColumnCount = 1;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 19);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 2;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 17F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 17F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(202, 229);
this.tableLayoutPanel2.TabIndex = 103;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.tableLayoutPanel1);
this.groupBox1.Location = new System.Drawing.Point(6, 15);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(208, 251);
this.groupBox1.TabIndex = 274;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "DI列表";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.AutoScroll = true;
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 19);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 17F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 17F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(202, 229);
this.tableLayoutPanel1.TabIndex = 102;
//
// richTextBox1
//
this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.richTextBox1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.richTextBox1.Location = new System.Drawing.Point(450, 215);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(728, 468);
this.richTextBox1.TabIndex = 256;
this.richTextBox1.Text = "";
this.richTextBox1.VisibleChanged += new System.EventHandler(this.richTextBox1_VisibleChanged);
//
// groupBox3
//
this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox3.Controls.Add(this.lblWarnMsg);
this.groupBox3.Controls.Add(this.panel1);
this.groupBox3.Controls.Add(this.lblThisSta);
this.groupBox3.Location = new System.Drawing.Point(10, 6);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(1168, 124);
this.groupBox3.TabIndex = 268;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "设备状态";
//
// lblWarnMsg
//
this.lblWarnMsg.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.lblWarnMsg.ForeColor = System.Drawing.Color.Red;
this.lblWarnMsg.Location = new System.Drawing.Point(267, 66);
this.lblWarnMsg.Name = "lblWarnMsg";
this.lblWarnMsg.Size = new System.Drawing.Size(856, 52);
this.lblWarnMsg.TabIndex = 224;
this.lblWarnMsg.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// panel1
//
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panel1.Controls.Add(this.chbMoveStop);
this.panel1.Controls.Add(this.lblInfo);
this.panel1.Controls.Add(this.btnVmiExit);
this.panel1.Controls.Add(this.btnVmiStart);
this.panel1.Controls.Add(this.chbDebug);
this.panel1.Controls.Add(this.btnVmiStop);
this.panel1.Controls.Add(this.chbAuto);
this.panel1.Location = new System.Drawing.Point(5, 15);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(1160, 48);
this.panel1.TabIndex = 273;
//
// chbMoveStop
//
this.chbMoveStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.chbMoveStop.AutoSize = true;
this.chbMoveStop.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.chbMoveStop.Location = new System.Drawing.Point(704, 10);
this.chbMoveStop.Name = "chbMoveStop";
this.chbMoveStop.Size = new System.Drawing.Size(84, 24);
this.chbMoveStop.TabIndex = 274;
this.chbMoveStop.Text = "暂停运动";
this.chbMoveStop.UseVisualStyleBackColor = true;
this.chbMoveStop.CheckedChanged += new System.EventHandler(this.chbMoveStop_CheckedChanged);
//
// lblInfo
//
this.lblInfo.AutoSize = true;
this.lblInfo.Location = new System.Drawing.Point(277, 5);
this.lblInfo.Name = "lblInfo";
this.lblInfo.Size = new System.Drawing.Size(56, 17);
this.lblInfo.TabIndex = 273;
this.lblInfo.Text = "运行信息";
//
// btnVmiExit
//
this.btnVmiExit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnVmiExit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnVmiExit.Location = new System.Drawing.Point(1023, 3);
this.btnVmiExit.Name = "btnVmiExit";
this.btnVmiExit.Size = new System.Drawing.Size(132, 39);
this.btnVmiExit.TabIndex = 4;
this.btnVmiExit.Text = "退出";
this.btnVmiExit.UseVisualStyleBackColor = true;
this.btnVmiExit.Click += new System.EventHandler(this.退出ToolStripMenuItem_Click);
//
// btnVmiStart
//
this.btnVmiStart.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnVmiStart.Location = new System.Drawing.Point(4, 3);
this.btnVmiStart.Name = "btnVmiStart";
this.btnVmiStart.Size = new System.Drawing.Size(132, 39);
this.btnVmiStart.TabIndex = 0;
this.btnVmiStart.Text = "启动";
this.btnVmiStart.UseVisualStyleBackColor = true;
this.btnVmiStart.Click += new System.EventHandler(this.btnVmiStart_Click);
//
// chbDebug
//
this.chbDebug.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.chbDebug.AutoSize = true;
this.chbDebug.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.chbDebug.Location = new System.Drawing.Point(932, 10);
this.chbDebug.Name = "chbDebug";
this.chbDebug.Size = new System.Drawing.Size(84, 24);
this.chbDebug.TabIndex = 271;
this.chbDebug.Text = "调试状态";
this.chbDebug.UseVisualStyleBackColor = true;
this.chbDebug.CheckedChanged += new System.EventHandler(this.chbDebug_CheckedChanged);
//
// btnVmiStop
//
this.btnVmiStop.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnVmiStop.Location = new System.Drawing.Point(139, 3);
this.btnVmiStop.Name = "btnVmiStop";
this.btnVmiStop.Size = new System.Drawing.Size(132, 39);
this.btnVmiStop.TabIndex = 1;
this.btnVmiStop.Text = "停止";
this.btnVmiStop.UseVisualStyleBackColor = true;
this.btnVmiStop.Click += new System.EventHandler(this.btnVmiStop_Click);
//
// chbAuto
//
this.chbAuto.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.chbAuto.AutoSize = true;
this.chbAuto.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.chbAuto.Location = new System.Drawing.Point(811, 10);
this.chbAuto.Name = "chbAuto";
this.chbAuto.Size = new System.Drawing.Size(112, 24);
this.chbAuto.TabIndex = 270;
this.chbAuto.Text = "开机自动启动";
this.chbAuto.UseVisualStyleBackColor = true;
this.chbAuto.CheckedChanged += new System.EventHandler(this.chbAuto_CheckedChanged);
//
// lblThisSta
//
this.lblThisSta.AutoSize = true;
this.lblThisSta.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.lblThisSta.ForeColor = System.Drawing.Color.Green;
this.lblThisSta.Location = new System.Drawing.Point(8, 83);
this.lblThisSta.Name = "lblThisSta";
this.lblThisSta.Size = new System.Drawing.Size(65, 19);
this.lblThisSta.TabIndex = 216;
this.lblThisSta.Text = "等待启动";
//
// FrmVMIClient
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(1184, 687);
this.Controls.Add(this.groupBox5);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.richTextBox1);
this.Controls.Add(this.groupBox3);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "FrmVMIClient";
this.Opacity = 0D;
this.Text = "空料架缓存线";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmTest_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FrmStoreBox_FormClosed);
this.Load += new System.EventHandler(this.FrmTest_Load);
this.Shown += new System.EventHandler(this.FrmStoreBox_Shown);
this.contextMenuStrip1.ResumeLayout(false);
this.groupBox5.ResumeLayout(false);
this.groupBox5.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.groupBox4.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label lblThisSta;
private System.Windows.Forms.RichTextBox richTextBox1;
private System.Windows.Forms.Label lblWarnMsg;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.Button btnLogDebug;
private System.Windows.Forms.Button btnClearL;
private System.Windows.Forms.Button btnVmiStart;
private System.Windows.Forms.Button btnVmiStop;
private System.Windows.Forms.CheckBox chbAuto;
private System.Windows.Forms.CheckBox chbDebug;
private System.Windows.Forms.Button btnVmiExit;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem 显示ToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator8;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
private System.Windows.Forms.GroupBox groupBox5;
private System.Windows.Forms.Button btnInLOutStopDown;
private System.Windows.Forms.Button btnInLInStopDown;
private System.Windows.Forms.Button btnInLineRun;
private System.Windows.Forms.Button btnCloseA;
private System.Windows.Forms.Button btnNeedEnter;
private System.Windows.Forms.Button btnNeedLeave;
private System.Windows.Forms.Button btnDis;
private System.Windows.Forms.Button btnInit;
private System.Windows.Forms.Label lblInfo;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private System.Windows.Forms.Button btnStopTDown;
private System.Windows.Forms.ComboBox cmbStopList;
private System.Windows.Forms.TextBox txtname;
private System.Windows.Forms.TextBox txtShelfId;
private System.Windows.Forms.Button btnNone;
private System.Windows.Forms.CheckBox chbMoveStop;
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.CompilerServices;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using log4net;
using UserFromControl;
using OnlineStore.DeviceLibrary;
using OnlineStore.Common;
using OnlineStore.VMILineClient;
using OnlineStore.LoadCSVLibrary;
namespace OnlineStore.VMILineClient
{
public partial class FrmVMIClient : FrmBase
{
private LineBean vmiLine;
public static readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public FrmVMIClient()
{
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
chbAuto.Checked = ConfigAppSettings.GetIntValue(Setting_Init.App_AutoRun).Equals(1);
}
#region "初始化界面数据"
private bool LoadOk = false;
private void FrmTest_Load(object sender, EventArgs e)
{
LogUtil.logBox = this.richTextBox1;
cmbStopList.SelectedIndex = 0;
this.vmiLine = LineManager.InitStore();
if (vmiLine == null)
{
LogUtil.error(LOGGER, "加载设备失败");
this.Close();
return;
}
timer1.Enabled = true;
groupBox5.Text = "AGV调度通信,入料线体 [" + vmiLine.Config.In_AgvName + "] ,出料线体 [" + vmiLine.Config.Out_AgvName + "] ";
chbDebug.Checked = vmiLine.IsDebug;
this.ShowInTaskbar = true;
LoadIOList();
txtname.Text = vmiLine.Config.In_AgvName;
notifyIcon1.Text = ConfigAppSettings.GetValue(Setting_Init.App_Title);
HideForm();
this.Opacity = 1;
LoadOk = true;
}
#endregion
Dictionary<string, IOTextControl> DIControlList = new Dictionary<string, IOTextControl>();
Dictionary<string, IOTextControl> DOControlList = new Dictionary<string, IOTextControl>();
private void LoadIOList()
{
int roleindex = 0;
this.tableLayoutPanel1.RowStyles.Clear();
this.tableLayoutPanel1.RowCount = vmiLine.Config.StoreDIList.Count;
foreach (ConfigIO ioValue in vmiLine.Config.StoreDIList.Values)
{
this.tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 26));
IOTextControl control = new IOTextControl(ioValue.ElectricalDefinition + "_" + ioValue.Explain, ioValue.ProName);
this.tableLayoutPanel1.Controls.Add(control, 0, roleindex);
roleindex++;
DIControlList.Add(ioValue.ProName, control);
}
tableLayoutPanel2.RowStyles.Clear();
this.tableLayoutPanel2.RowCount = vmiLine.Config.StoreDOList.Count;
roleindex = 0;
foreach (ConfigIO ioValue in vmiLine.Config.StoreDOList.Values)
{
this.tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 28));
IOTextControl control = new IOTextControl(ioValue.ElectricalDefinition + "_" + ioValue.Explain, ioValue.ProName);
this.tableLayoutPanel2.Controls.Add(control, 0, roleindex);
roleindex++;
DOControlList.Add(ioValue.ProName, control);
}
this.SuspendLayout(); //此处为不闪屏,一定要有的!
}
private void ReadIOList()
{
foreach (string key in DIControlList.Keys)
{
IOTextControl control = DIControlList[key];
int iov = (int)IOManager.IOValue(key);
if (iov != control.IOValue)
{
control.IOValue = iov;
control.ShowData();
}
}
foreach (string key in this.DOControlList.Keys)
{
IOTextControl control = DOControlList[key];
int iov = (int)IOManager.DOValue(key);
if (iov != control.IOValue)
{
control.IOValue = iov;
control.ShowData();
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (!this.Visible)
{
return;
}
ReadIOList();
lblThisSta.Text = LineManager.GetRunStr(vmiLine.runStatus) + " " + (vmiLine.IsSleep ? "休眠中" : "");
lblWarnMsg.Text = vmiLine.WarnMsg;
lblInfo.Text = vmiLine.GetRunInfo();
}
private void FrmTest_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)//当用户点击窗体右上角X按钮或(Alt + F4)时 发生
{
e.Cancel = true;
HideForm();
}
}
private void btnVmiStart_Click(object sender, EventArgs e)
{
if (vmiLine.runStatus >= RunStatus.HomeMoving)
{
btnVmiStart.Text = "复位";
vmiLine.Reset();
}
else if (vmiLine.StartRun())
{
btnVmiStart.Text = "复位";
}
else
{
btnVmiStart.Text = "启动";
}
}
private void btnVmiStop_Click(object sender, EventArgs e)
{
try
{
if (vmiLine.runStatus >= RunStatus.HomeMoving)
{
vmiLine.StopRun();
btnVmiStart.Text = "启动";
}
else
{
MessageBox.Show("清先启动VMI流水线");
}
}
catch (Exception ex)
{
LogUtil.error(LOGGER, "出错:" + ex.StackTrace);
}
}
private void btnLogDebug_Click(object sender, EventArgs e)
{
if (LogUtil.debug_opened == false)
{
btnLogDebug.Text = "关闭DEBUG";
LogUtil.debug_opened = true;
}
else
{
btnLogDebug.Text = "开启DEBUG";
LogUtil.debug_opened = false;
}
}
private void FrmStoreBox_Shown(object sender, EventArgs e)
{
}
private void chbAuto_CheckedChanged(object sender, EventArgs e)
{
if (!LoadOk)
{
return;
}
if (chbAuto.Checked)
{
ConfigAppSettings.SaveValue(Setting_Init.App_AutoRun, 1);
ManagerUtil.AutoRun(Application.ExecutablePath, true);
}
else
{
ConfigAppSettings.SaveValue(Setting_Init.App_AutoRun, 0);
ManagerUtil.AutoRun(Application.ExecutablePath, false);
}
}
private void ExitApp()
{
try
{
if (this.timer1.Enabled)
{
this.timer1.Enabled = false;
}
if (vmiLine.runStatus >= RunStatus.HomeMoving)
{
vmiLine.StopRun();
}
IOManager.instance.CloseAllDO();
IOManager.instance.CloseAllConnection();
LineManager.Line.AgvClient.Dispose();
System.Environment.Exit(System.Environment.ExitCode);
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace, "Exception(异常)", MessageBoxButtons.OK, MessageBoxIcon.Error);
LogUtil.error(LOGGER, ex.StackTrace);
}
}
/// <summary>
/// 隐藏窗口
/// </summary>
private void HideForm()
{
this.Opacity = 0;
this.ShowInTaskbar = false;
this.notifyIcon1.Visible = true;
this.Hide();
}
private void FrmStoreBox_FormClosed(object sender, FormClosedEventArgs e)
{
ExitApp();
}
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("是否确定退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result.Equals(DialogResult.Yes))
{
ExitApp();
}
}
private void btnClearL_Click(object sender, EventArgs e)
{
LogUtil.ClearLog();
}
private void chbDebug_CheckedChanged(object sender, EventArgs e)
{
if (!LoadOk)
{
return;
}
if (chbDebug.Checked)
{
if (!vmiLine.IsDebug)
{
DialogResult result = MessageBox.Show("是否切换到调试状态?", "是否确认切换", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (result.Equals(DialogResult.Yes))
{
vmiLine.IsDebug = true;
ConfigAppSettings.SaveValue(Setting_Init.IsInDebug, 1);
LogUtil.info("用户切换到调试状态 ");
}
}
}
else
{
if (vmiLine.IsDebug)
{
DialogResult result = MessageBox.Show("是否切换到正常工作状态?", "是否确认切换", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (result.Equals(DialogResult.Yes))
{
vmiLine.IsDebug = false;
ConfigAppSettings.SaveValue(Setting_Init.IsInDebug, 0);
LogUtil.info("用户切换到正常工作状态 ");
}
}
}
}
private void richTextBox1_VisibleChanged(object sender, EventArgs e)
{
LogUtil.UpdateLogbox();
}
private void 显示ToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Opacity = 100;
this.Visible = true;
this.WindowState = FormWindowState.Normal;
this.notifyIcon1.Visible = false;
this.ShowInTaskbar = true;
}
protected void BtnMove(Button btn, string defaultText, string targetText, string ioHighType)
{
LogUtil.info(vmiLine.Name + "点击【" + btn.Text + "】 ");
if (btn.Text.Equals(defaultText))
{
IOManager.IOMove(ioHighType, IO_VALUE.HIGH);
btn.Text = targetText;
btn.BackColor = Color.Aqua;
}
else
{
IOManager.IOMove(ioHighType, IO_VALUE.LOW);
btn.Text = defaultText;
btn.BackColor = Color.White;
}
}
private void btnInLineRun_Click(object sender, EventArgs e)
{
BtnMove(btnInLineRun, "线体运转", "线体停止", IO_Type.Line_Run);
}
private void btnInLInStopDown_Click(object sender, EventArgs e)
{
BtnMove(btnInLInStopDown, "阻挡下降", "阻挡上升", IO_Type.StopDown);
}
private void btnInLOutStopDown_Click(object sender, EventArgs e)
{
BtnMove(btnInLOutStopDown, "出口阻挡下降", "出口阻挡上升", IO_Type.OutStopDown);
}
private void btnCloseA_Click(object sender, EventArgs e)
{
vmiLine.StopMove();
}
string agvName = "C2";
private void btnNeedLeave_Click(object sender, EventArgs e)
{
LineManager.Line.AgvClient.NeedLeave(txtname.Text, txtShelfId.Text);
}
private void btnNeedEntry_Click(object sender, EventArgs e)
{
LineManager.Line.AgvClient.NeedEnter(txtname.Text, txtShelfId.Text);
}
private void btnInit_Click(object sender, EventArgs e)
{
LineManager.Line.AgvClient.Init(LineManager.Line.Config.In_AgvName, LineManager.Line.Config.Out_AgvName);
}
private void btnDis_Click(object sender, EventArgs e)
{
LineManager.Line.AgvClient.Dispose();
}
private void btnStopTDown_Click(object sender, EventArgs e)
{
int value = (int)numericUpDown1.Value;
//进料线_阻挡
//出料线_出口阻挡
string iotype = IO_Type.StopDown;
if (cmbStopList.SelectedIndex.Equals(1))
{
iotype = IO_Type.OutStopDown;
}
vmiLine.StopIOMove(iotype, value);
}
private void chbMoveStop_CheckedChanged(object sender, EventArgs e)
{
vmiLine.MoveStop = chbMoveStop.Checked;
LogUtil.info(vmiLine.Name + "用户切换是否暂停: " + vmiLine.MoveStop);
}
private void btnNone_Click(object sender, EventArgs e)
{
LineManager.Line.AgvClient.SetToNone(txtname.Text);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 16</value>
</metadata>
<metadata name="notifyIcon1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>392, 16</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>510, 16</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="notifyIcon1.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAA8AMDAQAAEABABoBgAA9gAAACgoEAABAAQAyAQAAF4HAAAgIBAAAQAEAOgCAAAmDAAAGBgQAAEA
BADoAQAADg8AABAQEAABAAQAKAEAAPYQAAAwMAAAAQAIAKgOAAAeEgAAKCgAAAEACACoCwAAxiAAACAg
AAABAAgAqAgAAG4sAAAYGAAAAQAIAMgGAAAWNQAAEBAAAAEACABoBQAA3jsAADAwAAABACAAqCUAAEZB
AAAoKAAAAQAgAGgaAADuZgAAICAAAAEAIACoEAAAVoEAABgYAAABACAAiAkAAP6RAAAQEAAAAQAgAGgE
AACGmwAAKAAAADAAAABgAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACA
gACAAAAAgACAAICAAACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAAwMDAAP///wAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAA/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAA
D///8AAAAAAAAAAAAAAAAAAAAAAAAAAE7////0AAAAAAAAAAAAAAAAAEZHZGBABP/////+AAQkJWZkAA
AAAAAAAG6+t3YAD///////8AB7brd2AAAAAAAAAHvtt0AA/////////kAEd77UAAAAAAAAAGt3ZgBO//
////////ACRnvlAAAAAAAAAHd0QAT///////////8EBHdmAAAAAAAAAEZ2QA////7uvb7v///kAkR0AA
AAAAAAAEdAAf///r69e+vb7///AAZ0AAAAAAAAAGUATv//vtvr2+t72+//9AB0AAAAAAAAAEAC///r6+
t76+vbe+7//gBCAAAAAAAAAABO//7t6+fX2+vre3vv//AAAAAAAAAAAAD///3r69t76+vb69vv//5AAA
AAAAAAAA///+vt5+3r7b69t723///wAAAAAAAAAP///3576+vre+vXvr23////AAAAAAAAD////73n19
7t6+vNvrdr7///8AAAAAAA7////t7r7ne+vtd9vr237////wAAAABP/////r7evt536+vr6+t7f////+
cAAAb//////r7r7evt7X1769vr3/////8AABD/////99fu5+7r7r7X6+t7f/////8AAAAP/////n7t7u
7Xfr6+vX233/////AAAAAA/////t7u7e7u3n7evr577////wAAAAAAD////+7u7u7t6+2+vr69////8A
AAAAAAAP///+3u7+7ufud33tt7////AAAAAAAAAA///+7u/u7e7evt6+vu///wAAAAAAAAAAD///7u7u
7u7N7r7evf//8AAAAAAAAAAEBP///u7u7ud9576+v//+QEAAAAAAAAAGcE7//u7u7t7r7efe7//wR0AA
AAAAAAAGe0D///7u7n5+fr6///8AfVAAAAAAAAALfXAP///u3n19vt7///BOt2AAAAAAAAAHd75A////
/u7u7v///kB3vrAAAAAAAAAE3rdwD///////////8ke+3kAAAAAAAAAE6+17ZP//////////AHvte3AA
AAAAAAAE6+vrcA/////////wRd63fVAAAAAAAAAG7XfXdgH///////8Aduvtd2AAAAAAAAAAVkdGVkAP
//////AGVkdGVgAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAA
AAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD///////8AAP///n///wAA///8P///AAD///gf//8AAP//8A///wAA///gB///AAD8AAAAAD8AAPwA
AAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/
AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD8AAAAAD8AAPgAAAAAHwAA8AAAAAAPAADgAAAAAAcAAMAA
AAAAAwAAgAAAAAABAACAAAAAAAEAAMAAAAAAAwAA4AAAAAAHAADwAAAAAA8AAPgAAAAAHwAA/AAAAAA/
AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwA
AAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD//+AH//8AAP//8A///wAA///4H///
AAD///w///8AAP///n///wAA////////AAAoAAAAKAAAAFAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//
AADAwMAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF
cAAAAAAAAAAAAAAAAAAAAAAAAH/3AAAAAAAAAAAAAAAAAAAAAAAH//9wAAAAAAAAAAAAAAAAQAAAAH//
//cAAAAABAAAAAAABHt2VkAH/////3AFa3t2AAAAAAAAfXt2AH//////9wBGd9VAAAAAAAC3dkQH////
////cAR7dgAAAAAAAGezAH/////////3BGZ2AAAAAAAAdkQH///uvr3u//9wBWcAAAAAAABkAH//++2+
vVvu//cERgAAAAAAAAQH//7et9vr29vv/3AEAAAAAAAAAH//6+e+t7e+t77/9wAAAAAAAAAH//7r1313
fb69tu//cAAAAAAAAH///m53e+t7e3vr7//3AAAAAAAH///uvtftfX3r22u+//9wAAAAAH///+vte+vr
6+vr6+7///cAAAAH////3nfu3u3r3r69tv///nAAAH/////r7evr6+vre9e+////9wAAf////75+7u3u
fn3rfbf////3AAAH////7e7t7uvtvrvr6////3AAAAB////u3u7t7ud+3r2+///3AAAAAAf//+7u7u7u
ve2+d37//3AAAAAAAH///u7v7u7r7evbf//3AAAAAAAAB///7u/t7Xfuvn7v/3AAAAAAAABAf//u7u7u
frd9vv/3BAAAAAAAAHdH//7u7n5+3tfv/3C3QAAAAAAAvVB//+7u1+vr7v/3C3cAAAAAAAB9e0f//+7n
7e7//3B96wAAAAAAALfeYH/////////3C+vmAAAAAAAAfr63R////////3B9e+ZAAAAAAAC3fXdwf///
///3C3fetwAAAAAAAGdnt2QH/////3BHZ7dnAAAAAAAAAAAAAAB////3AAAAAAAAAAAAAAAAAAAAAAf/
/3AAAAAAAAAAAAAAAAAAAAAAAH/3AAAAAAAAAAAAAAAAAAAAAAAAB3AAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////8AAAD//+f//wAAAP//w///AAAA//+B//8A
AAD//wD//wAAAPgAAAAfAAAA+AAAAB8AAAD4AAAAHwAAAPgAAAAfAAAA+AAAAB8AAAD4AAAAHwAAAPgA
AAAfAAAA+AAAAB8AAAD4AAAAHwAAAPgAAAAfAAAA+AAAAB8AAADwAAAADwAAAOAAAAAHAAAAwAAAAAMA
AACAAAAAAQAAAIAAAAABAAAAwAAAAAMAAADgAAAABwAAAPAAAAAPAAAA+AAAAB8AAAD4AAAAHwAAAPgA
AAAfAAAA+AAAAB8AAAD4AAAAHwAAAPgAAAAfAAAA+AAAAB8AAAD4AAAAHwAAAPgAAAAfAAAA+AAAAB8A
AAD4AAAAHwAAAP//AP//AAAA//+B//8AAAD//8P//wAAAP//5///AAAA//////8AAAAoAAAAIAAAAEAA
AAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICA
gAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AADAwMAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAG7gAAAAAAAAAAAAAAAAAADv/kAAAAAAAAAAAABARABO///gBARAAAAAAABH63tg
7////kZ3vrQAAAAAC+13Tv/////mt9dwAAAAAAfbdO///////gbr5AAAAABL5k7/7ut37v/iXXAAAAAA
DnDv/td729vv/kZ0AAAAAAZO/+vr6+vr6//lYAAAAAAA7/7r69t7e7v//gAAAAAATv/77efn13fbfv/k
AAAAAO//7ee+vbe9vr7//gAAAE7//+vt537uvr23///hAADv//933r7Xvbe3t////gAA7///5+7n7n7X
fXb///4AAA///+3u3u2+vr6+///mAAAA7//u7u7u7t69vv/+AAAAAA7//u/u7Xvr7c7/4AAAAAAA7/7u
7u7tfr3v/gAAAAAAB27/7+7ufuvu7+R0AAAAAEtw7/7u3r197/5GcAAAAAAO1U7//u7u7//gfrQAAAAA
S31w7//////+e11wAAAAAAfr607/////4WvtdAAAAABGd9dw7////kbm63AAAAAAAAQAAA7//+AABAAA
AAAAAAAAAAAA7/4AAAAAAAAAAAAAAAAAAA7nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA///////+f////D////gf//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD+AA
AAfAAAADgAAAAYAAAAHAAAAD4AAAB/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD//4
H////D////5///////8oAAAAGAAAADAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gAAAgAAAAICAAIAAAACAAIAAgIAAAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AADAwMAA////AAAA
AAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAf+cAAAAAAAAAQkYF7/9gBgYAAAAGvrdv///3vr5AAAAA
7mX/////R31AAAAAtl/+7r7v87cAAAAEd//b69vb/2dAAAAAT/7r6+vrf+cAAAAC/+vr7be3vv9wAAB/
/+3r5969vv/wAAf//33N6+t76///YAD//+3u5+3rt///cAB//+7u3te+3v/xAAAE//7u7u6+vv8gAAAA
f/7u7r197vYAAAAEZP/u7u6+/1ZAAAAA53/+7t7v925AAAAEt2H/////R74AAAAE7eZ////wft5AAAAA
BAQA//9wBAQAAAAAAAAAf/QAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAP//////5////8P//+AA
B//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//AAAP/gAAB/4AAAf/AAAP/4AAH/+AAB//gAAf/4AAH/+AA
B//gAAf/4AAH///D////5////////ygAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAMDA
wAD///8AAAAADnAAAAAAAADufgAAAAAFZH/+RkQAAG6+///k5AAARu/ut/d2AABO+9vr3+QAB+7u7b6+
9+Du/+2+vrf/537/7u7Xe/9+Dn/u7uvt/uAAR/7t6+/gAABn7u7u97YAAE5u///m5gAABlDv9wZQAAAA
AH7uAAAAAAAADnAAAAD+f////D///8AD///AA///wAP//8AD//+AAf//AAD//wAA//+AAf//wAP//8AD
///AA///wAP///w////+f///KAAAADAAAABgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAgEABAQEAAgICAANDQ0AEQkGABISEgAUFBQAGRkZAB0dHQAnFg4AKBYOAC4aEQA9IhYAJSUlACws
LAAxMTEAODg4AD4+PgBFJxkAUy8fAFozIQBlOSUAcD8qAHJAKgB2QywAeUQtAEBAQABFRUUASEhIAFNT
UwBXV1cAXV1dAGFhYQBlZWUAampqAG5ubgBycnIAeHh4AH5+fgCHTDIAiEwyAMlTLgDLVTAAzVkzAMxZ
NADMXDoA0Fw2ANNgOADUYjoA1WQ8ANhnPgDYaD8AsWRCANVnQgDaaUAA3GxDANhrRADdbUQA3nBGANF2
TgDXclAA3ntXAOBxRgDhc0kA4XRKAON2TADkd00A5HhNAOh8TwDme1AA5nxSAOh9UQDpf1QA5IFVAOuA
UwDoglYA7IJVAOmCWADthlkA7IdcAO2IXQDwh1kA8ohZAPGKXADyjF8A9IxeAN2LbwDdi3AA3ZJ6AO6L
YADvjGIA8Y1hAPSOYQDxj2QA9JBiAPGRZgD0kmYA8pNoAPOWawD0lWoA9JZsAPSYbgDml3kA9ZpxAPWd
dQD2n3gA9aB5APaifQD2poEA9qeEAPeohAD3q4gA962LAPCqjgD3ro0A97CPAPexkAD3tZYA+LCQAPiz
lAD4tJYA+LaZAPi5nQDotKMA6LWmAPi7oAD4vaIA+b6kAPG/rAD5wKYA+cKqAPnFrQDsxbkA+cawAPnJ
tAD5zLcA+s25APrPvAD60L0A2traANzc2wDc3NwA+tTDAPrWxgD72McA+tfIAPvZyQD7280A+93PAPzd
zwD73dAA/OTZAP3p4AD46+cA++/pAPzw6wD98uwA/fbyAP39/QAAAAAALwMAAFAEAABwBgAAkAkAALAK
AADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAA
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
AA78AAAAAD8ADvwAAAAAPwAO/AAAAAA/AA78AAAAAD8ADvwAAAAAPwAO/AAAAAA/AA78AAAAAD8ADvgA
AAAAHwAO8AAAAAAPAA7gAAAAAAcADsAAAAAAAwAOgAAAAAABAA6AAAAAAAEADsAAAAAAAwAO4AAAAAAH
AA7wAAAAAA8ADvgAAAAAHwAO/AAAAAA/AA78AAAAAD8ADvwAAAAAPwAO/AAAAAA/AA78AAAAAD8ADvwA
AAAAPwAO/AAAAAA/AA78AAAAAD8ADvwAAAAAPwAO/AAAAAA/AA78AAAAAD8ADvwAAAAAPwAO/AAAAAA/
AA7//+AH//8ADv//8A///wAO///4H///AA7///w///8ADv///n///wAO////////AA4oAAAAKAAAAFAA
AAABAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUFBQAMBwQACgoKAA4ODgAcDwoAHBAKABAQ
EAAeHh4ALRkQACkpKQAuLi4AMDAwADY2NgA6OjoAPT09AEUnGQBjNyQAYzgkAGQ4JABtPSgAcT8pAHJA
KgBCQkIARkZGAElJSQBOTk4AV1dXAFlZWQBdXV0AYWFhAGVlZQBoaGgAbGxsAHl5eQB+fn4AiU0zAJBR
NQCYVjgAp14+AKlfPgCqYD8AyVMuAMlULwDMVzEAz1s1ANJfOADTYDkA1WQ8ANloPwCuYkAAsmRCALVm
QwC2ZkQAxW9JANVnQQDZaUAA3GxCANhrRADdbkQA0GlJAN9wRQDXc1IA335aAOBxRwDgckkA4nRJAON3
TADjeE4A5XlNAOF/UwDnfVIA4X9UAOd+VADpflEA6YFWAOyCVQDphFcA6oNYAOmEWQDthlgA7YleAPKI
WgD0ilsA8IpdAPKMXgDeknkA6YpjAO2LYADyjmEA9I5hAPCPZAD0kGMA8pFmAPSSZQDxkmgA9JNoAPOU
aQD0lWoA9JZsAPSYbgD0mnEA9ZxzAPWddQD2n3gA9aF7APWifAD2pH4A6Z+EAOCdiQD2pYEA9qmGAPar
iAD3ro0A97GRAPe0lgD4tpgA97ibAPi5ngD3u6EA97yiAPi7oAD4vaIA+b6kAPnApwD4w6sA+cStAO3G
uQD5xrAA+ciyAPnJtAD5zbgA+tC+APTOwAD608EA+dXFAPvZyQD72swA+9zNAPzi1gD86N8A/Pn3APr6
+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
AAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR/wD5sf8A+9H/AP//
/wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx/wDPkf8A3LH/AOvR
/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR/wCMcf8AppH/AL+x
/wDa0f8A////AAAAAAAAAAAXFwAAAAAAAAAAAAAAAAAXFxcXAAAAAAAAAAACAwMBFyQkFwEDAwIAAAAA
AxAFFyQkJCQXBRADAAAAAAMFFyIYCwgRIRcFAwAAAAABFyITDQwJBwYhFwEAAAAXFyQbExIPDAoHESQX
FwAXFyQkFRYWFA8MCggkJBcXFxckJBodHBkUDgwLJCQXFwAXFyQeIB8dFhINGCQXFwAAAAEXIyAgHRYT
EyIXAQAAAAADBBcjHhoVGyIXBQMAAAAAAxAEFyQkJCQXBRADAAAAAAIDAwEXJCQXAQMDAgAAAAAAAAAA
FxcXFwAAAAAAAAAAAAAAAAAXFwAAAAAAAAD+fwAA/D8AAMADAADAAwAAwAMAAMADAACAAQAAAAAAAAAA
AACAAQAAwAMAAMADAADAAwAAwAMAAPw/AAD+fwAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAABAAAABQAAABAAAAAlAAAARgAAAHEAAACaAAAAvgAAAL4AAACaAAAAcAAA
AEYAAAAlAAAAEAAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAABAAA
AAUAAAAFAAAABgAAAAYAAAAGAAAABgAAAAYAAAALAAAAFQAAACoAAABKAAAAdAAAAKIAAADNAAAA+gAA
APoAAADNAAAAogAAAHQAAABKAAAAKQAAABUAAAAKAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAA
AAYAAAAFAAAABQAAAAQAAAADAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
AAYAAAAMAAAAEgAAABYAAAAXAAAAGAAAABgAAAAYAAAAGQAAABwAAAAmAAAAOAAAAFcAAAB+AAAAqAAA
ANIAAAD7HR0d/xwcHP8AAAD7AAAA0gAAAKgAAAB+AAAAVgAAADgAAAAmAAAAHAAAABkAAAAYAAAAGAAA
ABgAAAAYAAAAGAAAABgAAAAXAAAAFgAAABIAAAAMAAAABgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAABAAAABgAAABEAAAAhAAAAMQAAADsAAABAAAAAQQAAAEEAAABCAAAARQAAAE0AAABcAAAAdAAA
AJUAAAC3AAAA2gAAAPwfHx//2tra/9jY2P8dHR3/AAAA/AAAANkAAAC3AAAAlQAAAHQAAABcAAAATAAA
AEUAAABCAAAAQQAAAEEAAABBAAAAQQAAAEEAAABAAAAAOwAAADEAAAAhAAAAEQAAAAYAAAABAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAADAAAADAAAACEAAABAAAAAXwAAAHQAAAB9AAAAfwAAAIAAAACCAAAAhwAA
AJEAAAChAAAAtwAAAM4AAADlAAAA/B8fH//Z2dn//f39//39/f/X19f/HR0d/wAAAPwAAADlAAAAzgAA
ALcAAAChAAAAkQAAAIcAAACCAAAAgAAAAH8AAAB/AAAAfwAAAH8AAAB9AAAAdAAAAF8AAABAAAAAIQAA
AAwAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEgAAADEAAABfAAAAjQAAAKwAAAC5AAAAvQAA
AL8AAADBAAAAxgAAAM8AAADaAAAA5gAAAPEAAAD+HR0d/9ra2v/9/f3//f39//39/f/9/f3/2NjY/xwc
HP8AAAD9AAAA8QAAAOYAAADaAAAAzwAAAMYAAADBAAAAvwAAAL4AAAC+AAAAvgAAAL0AAAC5AAAArAAA
AI0AAABfAAAAMQAAABIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFgAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8fHx//2dnZ//39/f/9/f3//f39//39
/f/9/f3//f39/9jY2P8eHh7/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAKwAAABzAAAAOwAAABYAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAA
AP88Ihb/eUQt/3lELf92Qyz/cD8p/2U5Jf9TLx7/PSIW/ycWDv8QCQX/AAAA/x8fH//Z2dn//v7+//7+
/f/+/v3//v7+//7+/f/+/v7//v7+//7+/v/X19f/Hh4e/wAAAP8QCQX/JxYO/z0iFv9TLx//ZTkl/3A/
Kf92Qyz/eUQt/3lELf88Ihb/AAAA/wAAALkAAAB9AAAAQAAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAGAAAAGAAAAP95RC3/84la/++HWP/kgVT/0XZN/7BkQf+HTDH/WjMh/y4aEf8EAgH/HR0d/9ra
2v/+/v3//v7+//7+/f/+/v3//v7+//39/f/+/v7//v7+//7+/v/+/v3/2NjY/xwcHP8DAgH/LhkQ/1oz
If+HTDL/sWRB/9F2Tf/kgVX/74dZ//OJWv95RC3/AAAA/wAAAL0AAAB/AAAAQQAAABgAAAAGAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP95RC3/74dY/+SBVP/Qdk3/sGRB/4ZMMf9aMyH/LhoR/wMC
Af8fHx//2tra//7+/f/+/v3//v79//39/f/+/v3//v79//39/f/+/v7//v7+//7+/v/+/v3//f39/9jY
2P8eHh3/AwIB/y4aEf9aMyH/h0wy/7FkQf/Rdk3/5IFV/++HWf95RC3/AAAA/wAAAL4AAAB/AAAAQQAA
ABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP92Qyz/5YFV/9F2Tf+xZEH/h0wy/1oz
If8uGhD/BAIB/x8fH//Z2dn//v79//39/f/+/v3//v79//7+/f/9/f3//v79//7+/f/+/v7//v79//7+
/v/+/v7//f39//39/f/X19f/Hh4d/wQCAf8uGhH/WjMh/4dMMv+xZEL/0XZO/+WBVf92Qyz/AAAA/wAA
AL4AAAB/AAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP9wPyn/0XZO/7Fk
Qf+HTDL/WzMh/y4aEf8DAgH/HR0d/9ra2f/9/f3//v79//39/f/+/v3//v79//7+/f/9/f3//f39//7+
/f/+/v3//f39//7+/v/+/v3//f39//39/f/9/f3/2NjY/xwcG/8EAgH/LhoR/1szIf+ITDL/sWRB/9F2
Tv9wPyn/AAAA/wAAAL4AAAB/AAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAHAAA
AP9lOSX/sGRB/4ZLMf9aMiH/LhoR/wMCAf8fHx//2tra//7+/f/+/v7//v79//7+/f/77ej/8L+r/+aW
ef/ee1f/2GtE/9VnQf/XcU//3Ipv/+i0o//46eX//f39//7+/f/9/f3//v7+/9jY2P8dHR3/AwIB/y4Z
EP9aMiH/hkwx/7FkQf9lOSX/AAAA/wAAAL8AAACAAAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
AAEAAAALAAAAJgAAAP9TLx7/h0wx/1oyIf8uGhD/BAIB/x8fH//Z2dn//v7+//7+/v/+/v7//O/q/++q
jv/keE7/4HFG/91tQ//aakD/2GY+/9VjO//SXzj/0Fw1/81ZMv/MWjX/3ZF6//jq5v/+/v3//v7+//7+
/v/Y2Nf/HR0d/wMCAf8uGRD/WjIh/4dMMv9TLx//AAAA/wAAAMEAAACCAAAAQgAAABgAAAAGAAAAAAAA
AAAAAAAAAAAAAQAAAAUAAAAVAAAAOAAAAP89Ihb/WjMh/y4aEf8EAgH/HR0d/9ra2v/+/v7//v79//7+
/f/51sb/7Ihd/+h8T//leUz/4nVJ/+BxR//dbkT/2mtB/9hnP//VYzz/0l85/9BcNf/NWTL/ylUw/8xd
O//sxLj//v7+//7+/v/+/v7/2NjY/xwcG/8DAgH/LhkQ/1ozIf89Ihb/AAAA/wAAAMYAAACHAAAARQAA
ABkAAAAGAAAAAAAAAAAAAAABAAAABQAAABAAAAAqAAAAVwAAAP8nFg7/LhoR/wMCAf8fHx//2tra//7+
/v/+/v7//v79//rNuf/wh1n/7YNV/+qAU//ofVD/5XlO/+N2S//hckj/3m9F/9trQv/YZz//1WQ8/9Jf
Of/QXDb/zVkz/8pVL//JUy//57Sk//7+/v/+/v7//v7+/9jY2P8eHh3/AwIB/y4aEf8nFg7/AAAA/wAA
AM8AAACRAAAATAAAABwAAAAGAAAAAAAAAAEAAAAFAAAADwAAACUAAABJAAAAfgAAAP8QCQX/BAIB/x8f
H//Z2dn//f39//39/f/+/v3/+9jI//SMXf/yilv/74dZ/+2FV//rglX/6H5S/+Z7T//jd0z/4XNJ/95w
Rv/ba0P/2Gc//9VkPP/TYDn/0Fw2/81ZM//KVTD/yVMv/+zEuP/+/v3//v79//39/f/X19f/Hh4d/wQC
Af8QCQX/AAAA/wAAANoAAAChAAAAXAAAACYAAAAKAAAAAQAAAAUAAAAPAAAAJAAAAEYAAAB0AAAAqAAA
AP8AAAD/HR0d/9ra2v/+/v7//v79//7+/f/98ev/9JNo//OMXv/zjV7/8o1f//GKXf/uhlr/64NX/+l/
VP/me1D/5HhN/+FzSv/ecEb/22xD/9hnP//WZDz/02A5/9BcNv/NWTP/ylUw/8xdO//46ub//v7+//39
/f/+/v3/2NjY/xwcHP8AAAD/AAAA/wAAAOYAAAC3AAAAdAAAADgAAAAVAAAABQAAAA8AAAAkAAAARgAA
AHIAAACiAAAA0gAAAP8fHx//2trZ//39/f/9/f3//f39//7+/f/4t5n/841f//SOYP/0j2L/9I9i//OP
Yv/xjF//7ohc/+yEWf/pgFX/5nxS/+R4Tv/hdEr/3nBG/9tsQ//ZaED/1mQ8/9NgOf/QXDb/zVkz/8tV
MP/dkXr//v39//39/f/9/f3//v79/9jY2P8eHh7/AAAA/wAAAPEAAADPAAAAlQAAAFYAAAApAAAADwAA
ACAAAABCAAAAbwAAAKAAAADPAAAA+x8fH//Z2dn//v79//7+/f/+/v3//v79//3x6//0kWT/849h//SR
ZP/0kmX/9JJm//STZv/zkWX/8Y1i/+6JXv/shlr/6YFW/+Z9Uv/jeU7/4XRK/95wR//bbEP/2WhA/9Zk
PP/TYDn/0Fw2/81ZMv/MWTX/+Orl//39/f/+/v3//v79//39/f/X19f/Hh4e/wAAAP4AAADlAAAAtwAA
AHwAAABGAAAAIAAAADQAAABjAAAAmAAAAMwAAAD6HR0d/9ra2v/+/v7//v79//7+/v/+/v7//v7+//rN
uP/0kGL/9JJl//SUaP/0lWr/9JVr//SWa//0lWr/85No//GPZP/ui2D/64dc/+mCV//mfVP/43lO/+B0
Sv/ecEf/22xD/9loQP/WZDz/0mA5/9BcNf/NWTL/6LSj//7+/v/+/v7//v7+//7+/v/+/v7/2NjY/xwc
HP8AAAD8AAAA2AAAAKAAAABmAAAANQAAAEMAAAB5AAAAugAAAPofHx/+2tra//7+/v/+/v7//v7+//7+
/v/+/v7//v7+//ixkf/0k2f/9JZr//WYb//1mnH/9Zpx//Wacf/1mXD/9Jhv//SWbP/xkWf/74xi/+yH
Xf/pglj/5n1T/+N5T//hdEr/3nBH/9xsQ//ZaD//1WQ8/9JfOf/QXDX/3Ypv//7+/f/+/v7//v7+//7+
/v/+/v7//f39/9jY2P8dHR3/AAAA+wAAAL8AAAB7AAAAQwAAAEEAAACNAAAA9h8fH//Z2dn//v7+//39
/f/9/f3//v7+//7+/f/+/v7//v7+//ahe//0lmz/9Ztx//Wedv/1n3j/9aB5//Wgef/1n3j/9Z11//Wb
cv/0mG7/8pJp/++NY//siF3/6YJY/+Z9U//jeU7/4XRK/95wRv/bbEP/2Gc//9VjPP/SXzj/13JQ//7+
/f/+/v7//v7+//7+/v/+/v7//f39//39/f/X19f/HR0d/wAAAPYAAACOAAAAQQAAAFQAAADvHR0d/9ra
2v/9/f3//v7+//39/f/9/f3//f39//39/f/+/v3//f39//Wbcv/1m3L/9aB5//akf//2poL/9qeD//an
g//2pYH/9aN9//Wgef/1nXX/9Jlw//KTaf/vjWL/64dc/+iBV//mfVL/43hO/+FzSf/eb0b/22tC/9dn
Pv/VYzv/1WdB//39/f/+/v3//v79//39/f/9/f3//f39//39/f/9/f3/2NjY/xwcHP8AAADvAAAAVAAA
AEMAAADrHh4e/tvb2//+/v7//v7+//7+/v/+/v3//v7+//7+/v/+/v7//v79//aed//1oHn/9qeD//es
iv/3r47/97CQ//ewkP/3roz/9qqI//angv/2onz/9Z52//SZcP/ykmj/7oxh/+uHXP/pgVb/5nxS/+R4
Tf/hc0n/3m9G/9prQf/YZj7/2GtE//7+/f/+/v3//v79//7+/v/+/v7//f39//7+/v/9/f3/2tra/x0d
Hf4AAADqAAAAQQAAAAwAAABGAAAA6yAgIP7a2tr//v7+//39/f/9/f3//v79//7+/f/+/v7//f39//eq
iP/2pYH/966N//i1l//4uJz/+Lqe//i6nf/4t5n/97KT//etjP/2p4T/9aJ8//Wddf/0l27/8ZFm/+6L
YP/rhVr/6YBV/+Z7UP/kd0z/4XJI/91uRP/aakD/3ntX//39/f/+/v3//v79//7+/f/+/v3//f39//39
/f/Z2dn/Hx8f/gAAAOsAAABIAAAADAAAAAMAAAAMAAAARQAAAO0gICD+29vb//39/f/9/f3//v79//7+
/f/+/v3//v79//i9ov/2qoj/97WX//i+o//4wqr/+cSt//nEq//4wKf/+Luf//e0lv/3rYz/9qaC//Wg
ef/1m3L/85Vr//CPZP/uiV7/64RY/+l/U//me0//43ZL/99xRv/dbUP/5pZ5//7+/f/+/v3//v79//7+
/f/+/v3//f39/9nZ2f8fHx//AAAA7wAAAFQAAAASAAAABAAAAAAAAAADAAAADAAAAEUAAADrHh4e/tvb
2//+/v7//v7+//7+/v/+/v7//v79//vXx//3r47/+Lyg//nGr//5zLj/+s+7//nNuf/5ybP/+MOr//i7
oP/3s5T/9qqI//ajfv/1nXX/9Jhu//OTaP/wjWL/7ohc/+uDV//pflL/5XlO/+J1Sf/gcUb/8b+r//7+
/f/+/v3//v79//7+/v/+/v7/2tra/x0dHf8AAADzAAAAcQAAACMAAAAJAAAAAQAAAAAAAAAAAAAAAwAA
AA0AAABJAAAA7CAgIP/a2tr//v79//7+/f/+/v3//v79//308P/4tJb/+MCm//nMuP/61MP/+tfH//rW
xf/60b7/+cm0//jAp//4t5r/966N//amgf/1n3j/9Zlw//SVav/zkWX/8Yxf/+6HWv/rglX/6H1Q/+V4
TP/keE7/++3o//39/f/+/v3//v7+//7+/f/Z2dn/Hx8f/wAAAPgAAACeAAAASgAAABsAAAAGAAAAAAAA
AAAAAAAAAAAAAAAAAAQAAAASAAAAVQAAAP8gICD/29vb//7+/f/+/v3//f39//7+/f/60L3/+MCn//rO
u//62Mn/+9zP//vbzf/61sX/+c25//nErP/4up7/97CQ//eng//2oHn/9Zpx//WWa//0k2b/9I9i//GK
Xf/uhVj/64BT/+h8T//vqo3//v79//39/f/9/f3//v7+/9ra2v8fHx//AAAA/wAAAMwAAACFAAAARAAA
ABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAJAAAAIwAAAP8AAAD/Hh4e/9vb2//+/v7//v79//7+
/v/99vL/+cOq//nLt//618f/+93P//vcz//618f/+s+7//nFrf/4up7/97CQ//enhP/1oHn/9Zpx//SV
a//0kmb/9JBj//ONX//wiFr/7YNV/+yIXf/87+r//v7+//7+/f/+/v3/2tra/x0dHf8AAAD/AAAA/wAA
AMEAAACBAAAAQgAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGwAAAP9EJhn/EgoG/yAg
IP/a2tr//v7+//7+/v/+/v7//Ong//nFrv/50L3/+tfH//vYyf/61MP/+cy4//nDq//4uZz/96+P//an
g//1oHn/9Zpw//SVav/0kmX/9I9i//ONX//yi1z/8IdZ//nWxv/+/v7//v7+//7+/f/Z2dn/Hx8f/xMK
B/9FJxn/AAAA/wAAAL4AAACAAAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAA
AP9yQCr/sWRB/xEJBv8gICD/29vb//7+/f/+/v7//v7+//zj2P/4xa7/+cu3//nOu//5zLj/+cav//i+
pP/3tZf/9qyK//akf//1nnb/9Zhu//SUaP/0kWP/9I5g//OMXf/zjF7/+s25//7+/f/+/v7//v79/9ra
2f8fHx//EQoG/7JlQv9yQCr/AAAA/wAAAL4AAAB/AAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAGAAAAGAAAAP93Qyz/6INW/7FkQf8SCgb/Hh4e/9vb2//+/v7//v7+//7+/v/86eD/+cKq//jA
p//4v6b/+Lug//e1mP/3ro3/9qeD//Wgev/1mnH/9JVq//SSZf/0j2H/841f//WUaP/72Mj//v7+//7+
/v/+/v7/2tra/x0dHf8TCwf/smVC/+iCVv93Qyz/AAAA/wAAAL4AAAB/AAAAQQAAABgAAAAGAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP95RC3/8IdZ/+eCVv+wY0H/EgoG/yAgIP/a2tr//v7+//7+
/f/+/v7//fby//rQvf/3tJX/9q6O//aqiP/2pYH/9aB5//Wbcv/0lmz/9JJm//SPYv/0kWT/+LeZ//3x
6//+/v3//v7+//7+/v/Z2dn/IB8f/xMLB/+yZEL/54JW//CHWf95RC3/AAAA/wAAAL4AAAB/AAAAQQAA
ABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP96RS3/84la//CHWf/nglb/sWRB/xEK
Bv8gICD/29vb//7+/f/+/v7//v7+//7+/f/99PD/+9fH//m+o//3q4j/9p53//Wbcv/2oXv/+LGR//rN
uP/98ev//v79//7+/f/9/f3//v7+/9ra2v8gIB//EgoG/7JlQv/nglb/8IdZ//OJWv95RC3/AAAA/wAA
AL4AAAB/AAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAAAP96RS3/84la//OJ
Wv/wh1n/6INW/7FkQf8SCgb/Hh4e/9vb2//+/v7//v79//39/f/+/v3//v79//7+/f/9/f3//v79//39
/f/+/v7//v7+//7+/v/+/v3//f39//7+/f/9/f3/2tra/x0dHf8TCgf/smVC/+iCVv/wh1n/84la//OJ
Wv95RC3/AAAA/wAAAL0AAAB/AAAAQQAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAGAAA
AP96RS3/84la//OJWv/ziVr/8IdZ/+eCVv+wY0H/EgoG/yAgIP/a2tr//v7+//39/f/+/v3//v7+//7+
/f/+/v7//v7+//7+/f/+/v7//v7+//7+/v/+/v3//f39//7+/v/Z2dn/Hx8f/xMKB/+yZEL/54JW//CH
Wf/ziVr/84la//OJWv95RC3/AAAA/wAAALkAAAB9AAAAQAAAABgAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAFAAAAFgAAAP96RS3/84la//OJWv/ziVr/84la//CHWf/nglb/sWRB/xEJBv8gICD/29vb//7+
/f/+/v3//v7+//7+/f/+/v3//v7+//39/f/+/v3//v79//7+/v/+/v7//f39/9ra2v8gHx//EQoG/7Jl
Qv/nglb/8IdZ//OJWv/ziVr/84la//OJWv95RC3/AAAA/wAAAKwAAABzAAAAOwAAABYAAAAFAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAEAAAAEgAAAP96RS3/84la//OJWv/ziVr/84la//OJWv/wh1n/6INW/7Fk
Qf8SCgb/Hh4e/9vb2//+/v3//v79//7+/f/+/v3//v79//39/f/+/v7//v79//7+/v/+/v3/2trZ/x0d
Hf8TCwf/smVC/+iCVv/wh1n/84la//OJWv/ziVr/84la//OJWv95RC3/AAAA/wAAAI0AAABfAAAAMQAA
ABIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAAAAP89Ihb/ekUt/3pFLf96RS3/ekUt/3pF
Lf95RC3/d0Ms/3JAKv9EJhn/AAAA/yAgIP/a2tr//v7+//39/f/9/f3//v79//39/f/+/v3//v7+//7+
/v/Z2dn/Hx8f/wAAAP9FJxn/ckAq/3dDLP95RC3/eUQt/3lELf95RC3/eUQt/3lELf88Ihb/AAAA/wAA
AF8AAABAAAAAIQAAAAwAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8gICD/29vb//39/f/9/f3//v7+//39
/f/9/f3//v7+/9ra2v8fHx//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAADEAAAAhAAAAEQAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
AAYAAAAMAAAAEgAAABYAAAAXAAAAGAAAABgAAAAYAAAAGAAAABgAAAAbAAAAIwAAAFUAAADsHh4e/tvb
2//+/v7//v7+//7+/v/+/v7/2tra/h0dHf8AAADrAAAAVAAAACMAAAAbAAAAGAAAABgAAAAYAAAAGAAA
ABgAAAAYAAAAGAAAABgAAAAXAAAAFgAAABIAAAAMAAAABgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAEAAAADAAAABAAAAAUAAAAFAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAACQAA
ABIAAABJAAAA6yAgIP7a2tr//v7+//39/f/Z2dn/Hx8f/gAAAOoAAABIAAAAEgAAAAkAAAAGAAAABgAA
AAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAFAAAABQAAAAQAAAADAAAAAQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAQAAAAQAAAANAAAARQAAAO0gICD+29vb/tra2v4fHx/+AAAA7AAAAEQAAAANAAAABAAA
AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAAAAEIAAADqHh4e/h0dHf4AAADpAAAAQQAA
AAwAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAkAAAA9AAAA6QAA
AOgAAAA7AAAACQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAIAAAAFAAAANAAAADMAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAO/AAAAAAH
AA74AAAAAAMADvAAAAAAAQAO8AAAAAABAA7wAAAAAAEADvAAAAAAAQAO8AAAAAABAA7wAAAAAAEADvAA
AAAAAQAO8AAAAAABAA7wAAAAAAEADvAAAAAAAQAO4AAAAAABAA7AAAAAAAEADoAAAAAAAQAOAAAAAAAA
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
/f/9/f3//f39//39/f/9/f3//f39//7+/f/9/f3//f39//r6+v9lZWX/AgEB/y4aEP9kOCX/mVY4/8Vv
Sf+nXj7/AAAA/wAAALgAAABsAAAAKgAAAAoAAAABAAAAAAAAAAAAAAAAAAAABAAAABoAAAD/kFE1/5hW
OP9jNyT/LRkQ/wIBAf9oaGj/+/v7//7+/v/+/v3//fr4//TOwP/pn4T/335a/9hrRP/VZ0H/13NS/96S
ef/txbj//Pn3//7+/f/9/f3/+/v7/2VlZf8CAQH/LRkQ/2M3JP+YVjj/kFE1/wAAAP8AAAC5AAAAbAAA
ACoAAAAKAAAAAQAAAAAAAAAAAAAAAQAAAAkAAAAnAAAA/209KP9jOCT/LRkQ/wIBAf9oaGj/+/v7//7+
/f/+/v7/+NXG/+qKY//idUn/33BF/9xsQv/ZaD//1mQ8/9JfOP/PWzX/zFcx/9BpSf/tx7v//v79//7+
/v/7+/v/ZWVl/wIBAP8tGRD/Yzgk/209KP8AAAD/AAAAvQAAAG4AAAAqAAAACgAAAAEAAAAAAAAAAQAA
AAUAAAAXAAAAQgAAAP9FJxn/LRkQ/wIBAf9nZ2f//Pz8//7+/v/9/Pz/97uh/+yCVP/pfVD/5XpN/+J1
Sv/gcUf/3W1E/9lpQP/VZDz/0l85/89bNf/MVzH/yVMv/+Cdif/9/Pz//v7+//v7+/9lZWX/AgEB/y0Z
EP9FJxn/AAAA/wAAAMQAAAB2AAAALgAAAAoAAAABAAAAAAAAAAUAAAATAAAAMwAAAGwAAAD/HBAK/wIB
Af9oaGj/+/v7//7+/f/+/v3/+b6k//KKW//vhlj/7INW/+l/U//me0//43dM/+BySP/dbkX/2WlA/9Zl
PP/TYDn/z1s1/8xXMf/JUy7/4J2J//7+/f/+/v3/+/v6/2ZmZf8CAQH/HBAK/wAAAP8AAADRAAAAhwAA
ADkAAAAOAAAAAQAAAAUAAAATAAAAMAAAAGEAAACeAAAA/wAAAP9nZ2f/+/v7//7+/f/+/v3/+9rK//OM
Xv/zjF7/8oxe//CJXP/thVj/6YBV/+d8Uf/keE3/4HNJ/91uRf/aaUH/1mU9/9NgOf/PWzb/zFcx/8lU
L//tx7v//v79//39/f/7+/v/ZWVl/wAAAP8AAAD/AAAA4AAAAKEAAABSAAAAHAAAAAUAAAASAAAAMAAA
AGAAAACZAAAA0gAAAP9oaGj/+/v7//39/f/9/f3//fv5//Wcc//zjmD/9I9h//SPY//zj2L/8Itf/+2H
W//qglf/531S/+R4Tv/gc0r/3W9F/9pqQf/WZT3/02A5/89bNv/MVzH/0GlJ//z59//9/f3//v79//v7
+/9lZWX/AAAA/wAAAPAAAADCAAAAeQAAADgAAAATAAAAKgAAAFoAAACVAAAAzwAAAPxoaGj/+/v7//7+
/v/+/v7//v79//vYyP/0j2H/9JFk//SSZv/0k2f/9JNo//OSZv/wjWL/7Yhd/+qDWP/nflP/43hO/+Bz
Sv/dbkX/2mpB/9ZlPf/TYDn/z1s1/8xXMf/txbj//f39//7+/v/+/v3/+/v6/2VlZf8AAAD+AAAA4QAA
AKUAAABgAAAAKgAAAEIAAACBAAAAxwAAAPxnZ2f/+/v7//7+/v/+/v7//v7+//7+/v/4tpj/9JJl//SV
av/0l23/9Jhu//WYbv/0l23/85Rq//CPZf/til//6oRZ/+d+VP/jeU7/4HNK/91vRf/aaUH/1mU9/9Jf
Of/PWzX/35J5//7+/f/+/v7//v7+//7+/v/7+/v/ZWVl/wAAAP0AAADOAAAAhQAAAEIAAABIAAAAoAAA
APpoaGj/+/v7//7+/v/+/v3//v7+//7+/v/+/v7/9qJ8//SWbP/1m3L/9Z11//Wed//1nnf/9Z11//Wb
cv/0l27/8ZFn/+6LYP/qhFr/535U/+N5T//gc0r/3W5F/9ppQf/WZDz/0l84/9dzUv/9/f3//v7+//7+
/v/+/v7//f39//v7+/9lZWX/AAAA+wAAAKMAAABIAAAAYQAAAPRnZ2f/+/v7//7+/v/9/f3//f39//39
/f/+/v3//f39//Wacv/1nHT/9aJ8//algP/2poL/9qaC//akf//1oXv/9Z12//SZb//xkmj/7Ytg/+mE
Wf/nflP/43hO/+BzSf/dbkX/2WlA/9VkPP/VZ0H//f39//7+/f/9/f3//f39//39/f/9/f3/+vr6/2Vl
Zf8AAAD0AAAAYQAAAEwAAADxaGho/vv7+//+/v7//v7+//7+/f/+/v7//v7+//7+/f/2n3j/9qN9//ar
iP/3r4//97GR//exkf/3roz/9qmG//akf//1n3f/9Jlw//GRZ//til//6oNY/+d9Uv/keE3/4XJJ/91t
RP/ZaD//2GtE//39/f/+/v3//v79//7+/v/9/f3//v7+//v7+/9nZ2f+AAAA8AAAAEsAAAAKAAAATgAA
APFpaWn++/v7//39/f/9/f3//v7+//7+/f/9/f3/962M//aqh//3tJb/+Lqf//i9ov/4vKH/97ib//ey
k//2q4n/9qR+//Wddf/0l23/8I9k/+2IXf/qglf/53xR/+N3TP/fcUf/3GxC/99+Wv/9/f3//v79//7+
/f/+/v3//f39//v7+/9oaGj+AAAA8gAAAFIAAAALAAAAAgAAAAoAAABOAAAA8WhoaP78/Pz//f39//7+
/v/+/v3//v79//nErP/3sJD/+L6j//nGr//5ybT/+ciy//jDq//4u6D/97KT//aphv/1oXv/9Zpx//OU
af/wjWH/7Ydb/+qAVf/ne0//4nVK/99wRf/pn4T//f39//7+/f/+/v3//v7+//v7+/9nZ2f/AAAA9QAA
AGcAAAATAAAAAwAAAAAAAAACAAAACgAAAFAAAADxaWlp//v7+//+/v3//v7+//7+/f/84tb/97WX//nF
rv/60L7/+tXE//rTwf/5zbj/+MOr//i4nP/3ro3/9qR///WddP/0l2z/85Jm//CLX//thVj/6n9T/+Z6
Tv/idEj/9M/A//39/f/+/v7//v79//v7+/9oaGj/AAAA+QAAAJMAAAAyAAAADAAAAAEAAAAAAAAAAAAA
AAIAAAAOAAAAWwAAAP9paWn//Pz8//7+/f/+/v3//fv6//nBp//5x7H/+tbF//vczv/72sz/+tPB//nI
sv/5vaL/97GR//amgv/2nnf/9Zhu//STaP/zj2P/8Ilc/+yDVv/pflH/6Ypj//36+P/9/f3//v79//v7
+/9oaGj/AAAA/wAAAMkAAABxAAAAKwAAAAoAAAABAAAAAAAAAAAAAAAAAAAABQAAAB8AAAD/AQAA/2ho
aP/7+/v//v79//7+/v/86N//+cSt//rTwv/73M7/+9zO//rVxP/5yrT/+L2j//exkf/2p4P/9Z53//WY
bv/0k2f/9JBj//KNXv/vh1n/7IJU//jVx//+/v3//v79//v7+/9nZ2f/AQEA/wAAAP8AAAC6AAAAbQAA
ACoAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAMAAAAXAAAA/3E/Kf8MBwT/aWlp//v7+//+/v7//v7+//vc
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
AEsAAAAKAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAACAAAACQAAAEgAAADwAAAA7wAAAEYAAAAJAAAAAgAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAEAAAAFAAAAPwAAAD0AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAA//AA7wAAAAA/8ADvAAAAAB/wAO4AAAAAH/
AA7gAAAAAP8ADuAAAAAA/wAO4AAAAAD/AA7gAAAAAP8ADuAAAAAA/wAO4AAAAAD/AA7gAAAAAP8ADsAA
AAAA/wAOgAAAAAD/AA6AAAAAAP8ADgAAAAAA/wAOAAAAAAD/AA4AAAAAAP8ADgAAAAAA/wAOAAAAAAD/
AA4AAAAAAP8ADgAAAAAA/wAOAAAAAAD/AA4AAAAAAP8ADoAAAAAA/wAOwAAAAAD/AA7gAAAAAP8ADuAA
AAAA/wAO4AAAAAD/AA7gAAAAAP8ADuAAAAAA/wAO4AAAAAD/AA7gAAAAAP8ADuAAAAAA/wAO4AAAAAH/
AA7gAAAAAf8ADvAAAAAB/wAO+AAAAAf/AA7//gB///8ADv//AP///wAO//+B////AA4oAAAAIAAAAEAA
AAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAA
AAEAAAABAAAAAQAAAAIAAAAHAAAAGwAAAEgAAACIAAAAxQAAAMUAAACHAAAARwAAABsAAAAHAAAAAgAA
AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAA
AA0AAAARAAAAEwAAABMAAAATAAAAGAAAACoAAABUAAAAkQAAANINDQ39DAwM/QAAANIAAACQAAAAUwAA
ACoAAAAYAAAAEwAAABMAAAATAAAAEwAAABMAAAARAAAADQAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAA
AAYAAAAZAAAANwAAAEoAAABQAAAAUAAAAFQAAABhAAAAfwAAAKwAAADcDQ0N/cLCwv/BwcH/DAwM/QAA
ANwAAACsAAAAfwAAAGEAAABUAAAAUAAAAFAAAABQAAAAUAAAAEoAAAA3AAAAGQAAAAYAAAAAAAAAAAAA
AAAAAAABAAAADQAAADcAAAB4AAAAogAAAK4AAACwAAAAtgAAAMMAAADYAAAA7g0NDf7CwsL//f39//39
/f/BwcH/DAwM/gAAAO4AAADYAAAAwwAAALYAAACwAAAArwAAAK8AAACuAAAAogAAAHgAAAA3AAAADQAA
AAEAAAAAAAAAAAAAAAEAAAARAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8NDQ3/wsLC//39
/f/9/f3//f39//39/f/BwcH/DAwM/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAogAA
AEoAAAARAAAAAQAAAAAAAAAAAAAAAQAAABMAAAD/84la/+6GWP/be1H/r2NB/3A/Kf8tGRD/Dg4N/8PD
wv/+/v3//v79//7+/f/9/f3//v7+//7+/v/BwcH/Dg0N/y0ZEP9wPyn/sGNB/9t8Uf/uhlj/84la/wAA
AP8AAACuAAAAUAAAABMAAAABAAAAAAAAAAAAAAABAAAAEwAAAP/uhlj/23tR/7BjQf9wPyn/LRkQ/w4O
Df/Dw8P//v7+//7+/f/+/v3//v79//39/f/+/v7//v7+//39/f/BwcH/Dg0M/y0ZEP9xPyn/sGNB/9t8
Uf/uhlj/AAAA/wAAAK8AAABQAAAAEwAAAAEAAAAAAAAAAAAAAAEAAAATAAAA/9t8Uf+wY0H/cUAp/y0Z
EP8ODg3/w8PC//7+/f/9/f3//v79//7+/f/9/f3//f39//7+/f/+/v3//f39//39/f/BwcH/Dg0N/y0Z
EP9xQCr/sGNB/9t8Uf8AAAD/AAAArwAAAFAAAAATAAAAAQAAAAAAAAAAAAAAAgAAABgAAAD/r2NB/3A/
Kf8tGRD/Dg4N/8PDw//+/v7//v79//nm3v/trZT/4YNh/9lrRP/VZkD/13ZW/+GeiP/14Nn//v79//7+
/f/BwcH/Dg0N/y0ZEP9wPyn/sGNB/wAAAP8AAACwAAAAUAAAABMAAAABAAAAAAAAAAAAAAAHAAAAKgAA
AP9wPyn/LRkQ/w4ODf/Dw8P//v7+//36+P/ztZr/53tO/+J1Sf/ecEX/22tB/9ZlPf/SXzn/zlo0/8tW
Mf/fmYT//Pn3//7+/v/BwcH/Dg0M/y0ZEP9wPyn/AAAA/wAAALYAAABUAAAAEwAAAAEAAAAAAAAABQAA
ABsAAABUAAAA/y0ZEP8ODg3/w8PC//7+/v/9+vn/9qiG/+6FV//qgFP/53tQ/+N2S//fcUf/22tC/9dm
Pf/SYDn/zlo0/8pVL//Xf2T//Pn3//7+/f/BwcH/Dg0M/y0ZEP8AAAD/AAAAwwAAAGEAAAAYAAAAAgAA
AAUAAAAZAAAARwAAAJAAAAD/Dg4N/8PDw//+/v7//v79//i7oP/zjF3/8oxe/++IWv/rg1b/531S/+R3
Tf/fcUj/22xD/9dmPv/TYDn/zlo0/8pVMP/fmYT//v79//39/f/BwcH/Dg0N/wAAAP8AAADYAAAAfwAA
ACoAAAAGAAAAGAAAAEYAAACKAAAA0g0NDf/Dw8L//f39//39/f/86uL/9I5g//SPYv/0kGP/849j/++K
Xv/shVn/6H9U/+R4Tv/fckj/22xD/9dmPv/TYDn/z1s1/8tWMf/14Nn//f39//7+/f/BwcH/DAwM/wAA
AO4AAACsAAAAUwAAABkAAAA6AAAAgQAAAM4NDQ39w8PD//7+/v/+/v7//v7+//i+pP/0kWT/9JNo//SV
af/0lWr/85Nn/++NYv/shlv/6H9V/+N5Tv/fckj/22xD/9dmPv/TYDn/zlo0/+GeiP/+/v3//v7+//7+
/v/BwcH/DAwM/gAAANsAAACJAAAAOgAAAFAAAAC1DQ0N/cPDw//+/v7//v7+//7+/v/+/v7/9qR///SW
a//1mnH/9Ztz//Wbc//1mnH/9JZs//CPZf/sh13/54BV/+N5T//fckj/22xD/9dmPv/SXzj/13dW//7+
/f/+/v7//v7+//39/f/BwcH/DAwM/QAAALkAAABRAAAAcA0NDfrDw8P//v7+//39/f/+/v3//v79//39
/f/1mnH/9Z52//ajfv/2pYH/9qWA//aifP/1nnb/9Jhv//CQZv/rh13/539V/+N4Tv/fckj/22tC/9Zl
Pf/VZkD//f39//39/f/+/v3//f39//39/f/BwcH/DAwM+gAAAHAAAABVDQ0N9sPDw//+/v7//f39//7+
/v/+/v7//v79//agev/2p4P/96+P//eyk//3spL/962M//ang//2oHn/9Jlv//CPZP/rhlv/6H5U/+R3
Tf/gcUf/2mpB/9lsRf/+/v3//v79//7+/v/9/f3//f39/8PDw/8NDQ32AAAAVAAAAAgAAABWDQ0N9sPD
w//9/f3//v79//7+/f/+/v3/97KT//exkf/4vaL/+cGo//jAp//4up7/97GR//ang//1nnb/85Zs/++N
Yf/rhFn/531S/+N2S//eb0X/4YNh//7+/f/+/v3//v79//39/f/CwsL/DQ0N+AAAAF8AAAAJAAAAAQAA
AAgAAABXDQ0N98PDw//+/v3//v79//7+/f/6zrr/+Lqd//nKtP/60L7/+c67//nGr//4up7/962M//ai
fP/1mXD/85Jn/++KXv/rg1b/53xQ/+J1Sf/trZT//v79//7+/v/+/v3/wsLC/w0NDfsAAACFAAAAGgAA
AAIAAAAAAAAAAQAAAAkAAABgDQ0N/8TEw//+/v3//v79//3w6v/4vaP/+tG+//vazP/72cr/+s+7//nB
p//3spL/9qWA//Wbc//0lWr/849j/++IW//rgVT/53tP//nm3v/9/f3//v7+/8PDwv8NDQ3/AAAAxAAA
AFUAAAATAAAAAQAAAAAAAAAAAAAAAgAAABoAAAD/FREQ/8TEw//+/v7//v7+//vZyf/5zbn/+9rM//vb
zP/60L7/+cKp//ezk//2pYH/9Ztz//SVaf/0kGP/8oxe/+6FV//ztZr//v7+//7+/f/Dw8P/FREQ/wAA
AP8AAACxAAAAUQAAABMAAAABAAAAAAAAAAAAAAABAAAAEwAAAP+hWjv/FREQ/8TEw//+/v3//vz7//rT
wf/5zbn/+tG+//nKtP/4vaL/96+P//ajfv/1mnH/9JNo//SPYf/zjF3/9qmG//36+f/+/v7/w8PC/xUR
EP+iWzz/AAAA/wAAAK8AAABQAAAAEwAAAAEAAAAAAAAAAAAAAAEAAAATAAAA/+yFWP+hWzv/FREQ/8TE
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
rEGAAKxBgACsQYAArEHAAaxB/D+sQQ==
</value>
</data>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>56</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
S/+ye0v/sntL/7J7S/+ye0v/sntL/0lAH9w0ShZ/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAhMBDjbqEy6j5aHNtxVTDasntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/r3lK/CQqEOxAYyMkAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAM0oYjTtWG9t7tDj/cqc08SQrEfCye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/kGY+3yIvEOIAAAAAAAAAAAAA
AAAAAAAAAAAAAD5YGh0eLA7uerI3/Hu0OP97tDj/OVMZ3WtSLtmye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/S0Eg3TJH
F5AAAAAAAAAAAAAAAAAAAAAAKToTzleAJ957tDj/e7Q4/3u0OP94sDf5ICkP8Kd0RvOye0v/sntL/7J7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+veUr6HyYP8ENZIRcAAAAAAAAAADdPGFQrPxTle7Q4/3u0OP97tDj/e7Q4/3u0OP9eiSveNzUY5bJ7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+ye0v/sntL/7J7S/90VTHaKTwTwAAAAAAAAAAAIjIQ4W2fMex7tDj/e7Q4/3u0OP97tDj/e7Q4/3u0
OP82TxneZE4q2bJ7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7
S/+ye0v/sntL/7J7S/+ye0v/sntL/7J7S/8kKhDtQFkaFCo9FGgqPRPme7Q4/3u0OP97tDj/e7Q4/3u0
OP97tDj/e7Q4/3qzOP0fKw7uMC4V6FdHJdt0VzHahWA53ZNoPuSWaT/mjWQ84XRVMdpfSynaNS8X5TQy
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
AP//gAD//4AB///AAf//wAP//+AH////////////
</value>
</data>
</root>
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;
namespace OnlineStore.VMILineClient
{
public class ManagerUtil
{
public static void AutoRun(string strName, bool value)
{
try
{
//创建启动对象
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
//设置运行文件
startInfo.FileName = System.Windows.Forms.Application.StartupPath + "\\AuToRunManager.exe";
//设置启动参数
startInfo.Arguments = String.Join(" ", new string[2] { strName, value.ToString() });
//设置启动动作,确保以管理员身份运行
startInfo.Verb = "runas";
//如果不是管理员,则启动UAC
System.Diagnostics.Process.Start(startInfo);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
using log4net;
using log4net.Config;
using OnlineStore.Common;
using OnlineStore.VMILineClient;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OnlineStore.VMILineClient
{
static class Program
{
#region 方法四:使用的Win32函数的声明
/// <summary>
/// 找到某个窗口与给出的类别名和窗口名相同窗口
/// </summary>
/// <param name="lpClassName">类别名</param>
/// <param name="lpWindowName">窗口名</param>
/// <returns>成功找到返回窗口句柄,否则返回null</returns>
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 切换到窗口并把窗口设入前台,类似 SetForegroundWindow方法的功能
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="fAltTab">True代表窗口正在通过Alt/Ctrl +Tab被切换</param>
[DllImport("user32.dll ", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
/// <summary>
/// 设置窗口的显示状态
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指示窗口如何被显示</param>
/// <returns>如果窗体之前是可见,返回值为非零;如果窗体之前被隐藏,返回值为零</returns>
[DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
public const int SW_RESTORE = 9;
public static IntPtr formhwnd;
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] Args)
{
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// 因为方法三只能是最小化的窗体显示出来,如果隐藏到托盘中则不能把运行的程序显示出来
Process currentproc = Process.GetCurrentProcess();
Process[] processcollection = Process.GetProcessesByName(currentproc.ProcessName.Replace(".vshost", string.Empty));
// 该程序已经运行,
bool isShow = false;
if (processcollection.Length >= 1)
{
foreach (Process process in processcollection)
{
if (process.Id != currentproc.Id)
{
// 如果进程的句柄为0,即代表没有找到该窗体,即该窗体隐藏的情况时
if (process.MainWindowHandle.ToInt32().Equals(0))
{
string formTitle = ConfigAppSettings.GetValue(Setting_Init.App_Title);
// 获得窗体句柄
formhwnd = FindWindow(null, formTitle);
// 重新显示该窗体并切换到带入到前台
ShowWindow(formhwnd, SW_RESTORE);
SwitchToThisWindow(formhwnd, true);
isShow = true;
break;
}
else
{
// 如果窗体没有隐藏,就直接切换到该窗体并带入到前台
// 因为窗体除了隐藏到托盘,还可以最小化
SwitchToThisWindow(process.MainWindowHandle, true);
isShow = true;
break;
}
}
}
}
if (!isShow)
{
log4net.Config.XmlConfigurator.Configure();
// XmlConfigurator.Configure();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmVMIClient());
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
LogUnhandledException(e.ExceptionObject);
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
LogUnhandledException(e.Exception);
}
static void LogUnhandledException(object exceptionobj)
{
//这里可以进一步地写日志
LOGGER.Error(exceptionobj.ToString());
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("VMILineClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VMILineClient")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("1b0a0559-e045-4edb-9dac-740eb0d8bb52")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace OnlineStore.VMILineClient.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OnlineStore.VMILineClient.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace OnlineStore.VMILineClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
ready是对接上流水线,arrive是在流水线附近等开门,所有节点都会发这两个事件,环形线和vmi只记录arrive的日志
20200217
Mayleave、MayEnter是包装料仓的,开了门后发,环形线和VMI是不用的。状态不需要重复设置。
20200220
agvclien增加cancelState的参数设置
20200221
agv客户端启动时需要设置状态为none
20200227
vmi链条增加休眠功能
20200302
VMI阻挡下降时间改为2秒
rfid是000时不发needLeave
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
//这里利用AttributeUsage 来设置我们的自定义属性的应用范围,这里定义的可以用于类,结构和方法的声明
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class CSVAttribute : Attribute
{
public CSVAttribute(string fieldName)
{
FieldName = fieldName;
}
private string fieldName;
public string FieldName
{
get { return fieldName; }
set { fieldName = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class CVSFieldNotMatchingExection : ApplicationException
{
public CVSFieldNotMatchingExection(string message)
: base(message)
{
}
public override string Message
{
get
{
return base.Message;
}
}
}
public class PositionAlreadyExistingExection : ApplicationException
{
public PositionAlreadyExistingExection(string message)
: base(message)
{
}
public override string Message
{
get
{
return base.Message;
}
}
}
}
using log4net;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class CSVReaderBase
{
public static char Spilt_Char = ',';
public static readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// 获取一个类所有的《字段,AttributeName列名》集合
/// </summary>
public static Dictionary<string, string> getProAttributeMap(Type type)
{
Dictionary<string, string> proCsvMap = new Dictionary<string, string>();
PropertyInfo[] props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
object[] array = prop.GetCustomAttributes(false);
if (array.Length > 0)
{
CSVAttribute att = (CSVAttribute)array[0];
if (att != null)
{
string csvName = att.FieldName;
proCsvMap.Add(prop.Name, csvName);
}
}
}
return proCsvMap;
}
/// <summary>
/// 获取一个类所有的《字段,AttributeName列名》集合
/// </summary>
public static Dictionary<string, string> getConfigProAttributeMap(Type type)
{
Dictionary<string, string> proCsvMap = new Dictionary<string, string>();
PropertyInfo[] props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
object[] array = prop.GetCustomAttributes( false);
if (array.Length > 0)
{
ConfigProAttribute att = (ConfigProAttribute)array[0];
if (att != null)
{
string csvName = att.FieldName;
if (proCsvMap.ContainsKey(csvName))
{
}
else
{
proCsvMap.Add(csvName, prop.Name);
}
}
}
}
return proCsvMap;
}
/// <summary>
/// 读取一个csv文件的所有内容
/// </summary>
protected static string[] ReadCSVFile(string filePath)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException("未找到文件:" + filePath);
}
string[] lines = File.ReadAllLines(filePath, Encoding.GetEncoding("gbk"));
return lines;
}
/// <summary>
/// 把数据写入csv中
/// </summary>
protected static bool WriteCSVFile(string filePath, string[] lines)
{
try
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
File.WriteAllLines(filePath, lines, Encoding.GetEncoding("gbk"));
//备份保存
try
{
FileInfo file = new FileInfo(filePath);
string date = DateTime.Now.ToString("yyyy-MM-dd");
string targetBackPath = @"C:\configBack\" + date + @"\";
if (!Directory.Exists(targetBackPath))
{
Directory.CreateDirectory(targetBackPath);
}
string fileName = file.Name;
string backFile = targetBackPath + fileName;
if (File.Exists(backFile))
{
File.Delete(backFile);
}
File.WriteAllLines(backFile, lines, Encoding.GetEncoding("gbk"));
}
catch (Exception e)
{
LOGGER.Error("出错:", e);
}
}
catch (Exception ex)
{
LOGGER.Error(ex.ToString());
return false;
}
return true;
}
protected static Dictionary<string, int> GetAllTitleIndex(string lineValue)
{
Dictionary<string, int> titleIndex = new Dictionary<string, int>();
var array = lineValue.Split(',');
//验证列
for (int i = 0; i < array.Length; i++)
{
string title = array[i];
titleIndex.Add(title, i);
}
return titleIndex;
}
protected static Dictionary<string, int> GetTitleIndex(string lineValue, List<string> cvsTitleList)
{
Dictionary<string, int> titleIndex = new Dictionary<string, int>();
var array = lineValue.Split(',');
//验证列
for (int i = 0; i < array.Length; i++)
{
string title = array[i];
if (cvsTitleList.Contains(title))
{
titleIndex.Add(title, i);
}
}
if (titleIndex.Count < cvsTitleList.Count)
{
foreach (string str in cvsTitleList)
{
if (!titleIndex.ContainsKey(str))
{
LOGGER.Error("未找到必须列:" + str + ",加载数据失败!");
throw new CVSFieldNotMatchingExection("未找到必须列:" + str + ",加载数据失败!");
}
}
}
return titleIndex;
}
protected static void BackConfig(string filePath, string[] lines)
{
////备份保存
//try
//{
// FileInfo file = new FileInfo(filePath);
// string date = DateTime.Now.ToString("yyyy-MM-dd");
// string targetBackPath = @"C:\configBack\" + date + @"\";
// if (!Directory.Exists(targetBackPath))
// {
// Directory.CreateDirectory(targetBackPath);
// }
// string fileName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "." + file.Name;
// string backFile = targetBackPath + fileName;
// if (File.Exists(backFile))
// {
// File.Delete(backFile);
// }
// File.WriteAllLines(backFile, lines, Encoding.GetEncoding("gbk"));
//}
//catch (Exception e)
//{
// LogUtil.error("备份【" + filePath + "】到C:configBack出错:" + e.ToString());
//}
//备份保存
try
{
FileInfo file = new FileInfo(filePath);
string date = DateTime.Now.ToString("yyyy-MM-dd");
string targetBackPath = @"D:\configBack\" + date + @"\";
if (!Directory.Exists(targetBackPath))
{
Directory.CreateDirectory(targetBackPath);
}
string fileName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + "." + file.Name;
string backFile = targetBackPath + fileName;
if (File.Exists(backFile))
{
File.Delete(backFile);
}
File.WriteAllLines(backFile, lines, Encoding.GetEncoding("gbk"));
}
catch (Exception e)
{
LogUtil.error("备份【" + filePath + "】到D:configBack出错:" + e.ToString());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class CSVConfigReader : CSVReaderBase
{
private static Dictionary<Type, Dictionary<string, string>> allItemProTitleMap = null;
/// <summary>
/// 获取一个类所有的《字段,AttributeName列名》集合
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private static Dictionary<string, string> GetProMapByType(Type type)
{
if (allItemProTitleMap == null)
{
allItemProTitleMap = new Dictionary<Type, Dictionary<string, string>>();
}
if (!allItemProTitleMap.ContainsKey(type))
{
allItemProTitleMap.Add(type, getProAttributeMap(type));
}
return allItemProTitleMap[type];
}
public static List<ConfigBase> ReadConfig(string filePath)
{
List<ConfigBase> configList = new List<ConfigBase>();
string[] lines = ReadCSVFile(filePath);
int index = 0;
Dictionary<string, int> allTitleIndex = new Dictionary<string, int>();
int typeIndex = -1;
foreach (var line in lines)
{
if (index == 0)
{
//根据配置表来读取数据
allTitleIndex = GetAllTitleIndex(line);
//必须有列【类型】
if (allTitleIndex.Count < 0 || !allTitleIndex.ContainsKey("类型"))
{
LOGGER.Error("未找到必须列:类型,加载数据失败!");
throw new CVSFieldNotMatchingExection("未找到必须列:类型,加载数据失败!");
}
typeIndex = allTitleIndex["类型"];
}
else
{
var array = line.Split(',');
//每一列必须有类型字段
string typeValue = array[typeIndex];
if (typeValue.Equals(""))
{
continue;
}
Type type = typeof(ConfigBase);
if (typeValue.Equals(ConfigItemType.DI) || typeValue.Equals(ConfigItemType.DO))
{
type = typeof(ConfigIO);
}
else if (typeValue.Equals(ConfigItemType.AXIS))
{
type = typeof(ConfigMoveAxis);
}
Dictionary<string, string> proTitleMap = getProAttributeMap(type);
ConfigBase bllIns = (ConfigBase)type.Assembly.CreateInstance(type.FullName);
//取得属性集合
PropertyInfo[] props = type.GetProperties();
int listIndex = 0;
List<string> proNameList = new List<string>(proTitleMap.Keys);
List<string> cvsTitleList = new List<string>(proTitleMap.Values);
List<string> checkFiledList = new List<string>(proNameList);
Dictionary<string, int> proIndexMap = new Dictionary<string, int>();
for (int i = 0; i<cvsTitleList.Count; i++)
{
proIndexMap.Add(cvsTitleList[i], i);
}
foreach (string key in cvsTitleList)
{
try
{
if (allTitleIndex.ContainsKey(key))
{
try
{
int titIndex = allTitleIndex[key];
string value = array[titIndex];
//string proName = proNameList[listIndex];
string proName = proNameList[proIndexMap[key]];
checkFiledList.Remove(proName);
PropertyInfo prop = props.First(c => c.Name == proName);//获取同名属性
if (prop != null && !value.Equals(""))
{
if (value.Equals("") && prop.PropertyType.Name.ToLower().Contains("int"))
{
prop.SetValue(bllIns, Convert.ChangeType(-1, prop.PropertyType), null);//赋值****在这里需要考虑类型问题
}
else if (value.Equals("") && prop.PropertyType.Name.ToLower().Contains("byte"))
{
prop.SetValue(bllIns, Convert.ChangeType(0, prop.PropertyType), null);//赋值****在这里需要考虑类型问题
}
else
{
prop.SetValue(bllIns, Convert.ChangeType(value, prop.PropertyType), null);//赋值****在这里需要考虑类型问题
}
}
}
catch (Exception ex)
{
LOGGER.Error("filepath=" + filePath + ",index=" + index + ",key=" + key + "出错:" + ex.ToString());
}
listIndex++;
}
}
catch (Exception ex)
{
LOGGER.Error("filepath=" + filePath + ",index=" + index + ",key=" + key + "出错:" + ex.ToString());
}
}
bllIns.CheckField();
configList.Add(bllIns);
}
index++;
}
return configList;
}
public static LineConfig LoadConfig(string filePath)
{
LineConfig config = null;
config = new LineConfig(filePath);
return LoadConfig(config);
}
public static LineConfig LoadConfig(LineConfig config)
{
LOGGER.Info("开始读取文件:" + config.ConfigFilePath);
if (config == null || config.ConfigFilePath.Equals(""))
{
return null;
}
List<ConfigBase> configList = ReadConfig(config.ConfigFilePath);
config.LoadConfig(configList);
return config;
}
public static bool SaveBoxPosition<T>(string filePath, T newConfig)
{
Type type = typeof(T);
//取得属性集合
PropertyInfo[] props = type.GetProperties();
string[] lines = ReadCSVFile(filePath);
BackConfig(filePath, lines);
int index = 0;
Dictionary<string, int> titleIndex = new Dictionary<string, int>();
string[] newLines = new string[lines.Length] ;
// 获取一个类所有的《字段,AttributeName列名》集合
Dictionary<string, string> proMap = GetProMapByType(typeof(ConfigBase));
List<string> proNameList = new List<string>(proMap.Keys);
List<string> csvNameList = new List<string>(proMap.Values);
Dictionary<string, int> allTitleIndex = new Dictionary<string, int>();
foreach (var line in lines)
{
newLines[index] = line;
var array = line.Split(',');
if (index == 0)
{
allTitleIndex = GetAllTitleIndex(line);
newLines[index] = line;
}
else
{
if (array.Length > 0 && array[0].ToString().Equals(ConfigItemType.PRO))
{
string[] newArray = array;
string proName = array[2];
string proValue = array[3];
try
{
PropertyInfo prop = props.First(c => c.Name == proName);//获取同名属性
if (prop != null)
{
string newValue = prop.GetValue(newConfig, null).ToString();
newArray[3] = newValue;
}
}
catch (Exception e) {
LOGGER.Error("出错:" + e.ToString());
}
string newLine = "";
foreach (string s in newArray)
{
newLine = newLine + s + ",";
}
newLines[index] = newLine;
}
}
index++;
}
return WriteCSVFile(filePath, newLines);
}
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
/// <summary>
/// 基础的属性配置
/// </summary>
public class ConfigBase
{
protected static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// DI=输入IO,DO=输出IO,PRO=属性,AXIS=轴
/// </summary>
[CSVAttribute("类型")]
public string ProType { get; set; }
/// <summary>
/// 说明
/// </summary>
[CSVAttribute("说明")]
public string Explain { get; set; }
/// <summary>
/// 名称
/// </summary>
[CSVAttribute("名称")]
public string ProName { get; set; }
/// <summary>
/// 属性值
/// </summary>
[CSVAttribute("属性值")]
public string ProValue { get; set; }
public virtual int GetValue()
{
if (ProValue.Equals(""))
{
return -1;
}
return Convert.ToInt32(ProValue);
}
public override string ToString()
{
return "ConfigBase。" + "类型:" + ProType + ",说明:" + Explain + ",名称:" + ProName + ",属性值:" + ProValue;
}
public virtual void CheckField()
{
if (String.IsNullOrEmpty(ProType) || String.IsNullOrEmpty(ProName) || String.IsNullOrEmpty(ProValue))
{
throw new CVSFieldNotMatchingExection(ToString() + ",【类型:ProType】【名称:ProName】【属性值:ProVale】必须配置值!");
}
}
}
/// <summary>
/// 运动轴配置
/// </summary>
public class ConfigMoveAxis : ConfigBase
{
/// <summary>
/// 使用AC伺服时表示串口号,使用康泰克运动版表示板卡名称
/// </summary>
[CSVAttribute("设备名称")]
public string DeviceName { get; set; }
/// <summary>
/// 待机位置
/// </summary>
//[CSVAttribute("默认值")]
public int DefaultPosition { get; set; }
/// <summary>
/// 目标速度
/// </summary>
//[CSVAttribute("目标速度")]
public int TargetSpeed { get; set; }
/// <summary>
/// 加速度
/// </summary>
//[CSVAttribute("加速时间")]
public short AddSpeed { get; set; }
/// <summary>
/// 减速度
/// </summary>
//[CSVAttribute("减速时间")]
public short DelSpeed { get; set; }
public int HomeLowSpeed { get; set; }
public int HomeHighSpeed { get; set; }
public int HomeAddSpeed { get; set; }
/// <summary>
/// 可以误差的脉冲范围的最小值
/// </summary>
public int CanErrorCountMin { get; set; }
/// <summary>
/// 可以误差的脉冲范围的最大值
/// </summary>
public int CanErrorCountMax { get; set; }
/// <summary>
/// 出入库目标值(只有出入库过程中才会有效)
/// </summary>
public int TargetPosition { get; set; }
///// <summary>
///// 速度倍率
///// </summary>
//public int ResolveSpeed { get; set; }
/// <summary>
/// 最小位置
/// </summary>
public int PositionMin { get; set; }
/// <summary>
/// 最大位置
/// </summary>
public int PositionMax { get; set; }
public string GetNameStr()
{
return DeviceName + "_" + GetAxisValue();
}
public bool IsSameAxis(string portName, int slv)
{
if (DeviceName.Equals(portName) && slv.Equals(GetAxisValue()))
{
return true;
}
return false;
}
public bool PositionIsHasLimit(){
if (PositionMin.Equals(PositionMax))
{
return false;
} return true;
}
/// <summary>
/// 下拉列表显示
/// </summary>
public string DisplayStr
{
get {
return Explain + "(" + ProName + ")";
}
set
{
}
}
public override int GetValue()
{
return GetAxisValue();
}
/// <summary>
/// 使用康泰克板卡表示轴编号,使用Ac伺服电机表示伺服地址
/// </summary>
/// <returns></returns>
public short GetAxisValue()
{
if (ProValue.Equals("") || ProValue.Equals("-1"))
{
return -1;
}
return (short)Convert.ToInt32(ProValue);
}
public override string ToString()
{
return "ConfigMoveAxis。" + "类型:" + ProType + ",说明:" + Explain + ",名称:" + ProName + ",属性值:" + ProValue + ",设备名称:" + DeviceName;
}
public override void CheckField()
{
if (String.IsNullOrEmpty( ProType) || String.IsNullOrEmpty( ProName ) || String.IsNullOrEmpty( DeviceName ) || String.IsNullOrEmpty( ProValue ))
{
throw new CVSFieldNotMatchingExection(ToString() + ",【类型:ProType】【名称:ProName】【属性值:ProVale】【设备名称:DeviceName】必须配置值!");
}
}
public bool IsMyAxis(string DeviceName, int AxisNo)
{
int AxisValue = GetAxisValue();
if (DeviceName.Equals(DeviceName) && AxisValue.Equals(AxisNo))
{
return true;
}
return false;
}
}
/// <summary>
/// io配置
/// </summary>
public class ConfigIO : ConfigBase
{
public ConfigIO()
{
SlaveID = 0;
}
private string IP = "";
/// <summary>
/// 设备IP
/// </summary>
public string IO_IP
{
get
{
if (String.IsNullOrEmpty(IP))
{
if (RobotConfig.ProIOIpMap != null && RobotConfig.ProIOIpMap.ContainsKey(DeviceName))
{
IP = RobotConfig.ProIOIpMap[DeviceName];
}
else
{
IP = DeviceName;
}
}
return IP;
}
}
/// <summary>
/// 设备名称
/// </summary>
[CSVAttribute("设备名称")]
public string DeviceName { get; set; }
/// <summary>
/// 描述
/// </summary>
[CSVAttribute("描述")]
public string Describe { get; set; }
/// <summary>
/// 电器定义
/// </summary>
[CSVAttribute("电器定义")]
public string ElectricalDefinition { get; set; }
/// <summary>
/// 代码定义
/// </summary>
[CSVAttribute("代码定义")]
public string CodeDefinition { get; set; }
/// <summary>
/// 默认值
/// </summary>
[CSVAttribute("默认值")]
public int DefaultValue { get; set; }
/// <summary>
/// SlaveID
/// </summary>
[CSVAttribute("SlaveID") ]
public byte SlaveID { get; set; }
private int IoValue = -10;
public string DisplayStr
{
get
{
return ElectricalDefinition + "_" + Explain + "(" + ProName+")";
}
set
{
}
}
public ushort GetIOAddr()
{
ushort value = 0;
try
{
value = (ushort)Convert.ToInt32(ProValue);
}
catch (Exception ex)
{
LOGGER.Error("出错:", ex);
}
return value;
}
public override string ToString()
{
return "ConfigIO。" + ProType + "," + Explain + "," + ProName + ",属性值:" + ProValue + ",设备名称:" + DeviceName + ",描述:" + Describe + ",电器定义:" + ElectricalDefinition + ",代码定义:" + CodeDefinition + "";
}
public override void CheckField()
{
if (String.IsNullOrEmpty(ProType) || String.IsNullOrEmpty(ProName) || String.IsNullOrEmpty(DeviceName) || String.IsNullOrEmpty(ProValue))
{
throw new CVSFieldNotMatchingExection(ToString() + ",【类型:ProType】【名称:ProName】【属性值:ProVale】【设备名称:DeviceName】必须配置值!");
}
}
}
public static class ConfigItemType
{
public static string DI = "DI";
public static string DO = "DO";
public static string AXIS = "AXIS";
public static string PRO = "PRO";
}
public static class ConfigItemName
{
/// <summary>
/// 上下转动轴
/// </summary>
public static string UpDown_Axis = "UpDown_Axis";
/// <summary>
/// 中转伝动轴 Middle_Axis
/// </summary>
public static string Middle_Axis = "Middle_Axis";
/// <summary>
/// 中轴移动速度 MiddleAxis_Move_Speed
/// </summary>
public static string MiddleAxis_Move_Speed = "MiddleAxis_Move_Speed";
/// <summary>
/// 上下轴普通速度 Updown_Move_Speed
/// </summary>
public static string Updown_Move_Speed = "Updown_Move_Speed";
/// <summary>
/// 上下轴慢速度 Updown_Move_Speed_Low
/// </summary>
public static string Updown_Move_Speed_Low = "Updown_Move_Speed_Low";
/// <summary>
/// 温湿度传感器地址 Temperate_ServerAddress
/// </summary>
public static string Temperate_ServerAddress = "Temperate_ServerAddress";
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
//这里利用AttributeUsage 来设置我们的自定义属性的应用范围,这里定义的可以用于类,结构和方法的声明
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class ConfigProAttribute : Attribute
{
public ConfigProAttribute(string fieldName)
{
FieldName = fieldName;
IsMust = true;
}
public ConfigProAttribute(string fieldName,bool ismust)
{
FieldName = fieldName;
IsMust = ismust;
}
private string fieldName;
public string FieldName
{
get { return fieldName; }
set { fieldName = value; }
}
/// <summary>
/// 是否必须的
/// </summary>
public bool IsMust { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class IO_Type
{
private static List<string> TypeList = null;
public static List<string> GetTypeList()
{
if (TypeList == null)
{
TypeList = new List<string>();
var p = typeof(IO_Type).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
foreach (var item in p)
{
TypeList.Add(item.Name);
}
}
return TypeList;
}
/// <summary>
///DI,急停,SuddenStop_BTN,0,PRO_AOI_IP_1,0,急停,X01,DI-01,0,
/// </summary>
public static string SuddenStop_BTN = "SuddenStop_BTN";
/// <summary>
/// DI,复位,Reset_BTN,1,PRO_AOI_IP_1,0,复位,X02,DI-02,0,
/// </summary>
public static string Reset_BTN = "Reset_BTN";
/// <summary>
/// DI,线体入口检测,InCheck,2,PRO_AOI_IP_1,0,线体入口检测,X03,DI-03,0,
/// </summary>
public static string InCheck = "InCheck";
/// <summary>
/// DI,线体阻挡检测,StopCheck1,3,PRO_AOI_IP_1,0,线体阻挡检测,X04,DI-04,0
/// </summary>
public static string StopCheck1 = "StopCheck1";
/// <summary>
///DI,线体出口检测,OutCheck,4,PRO_AOI_IP_1,0,线体出口检测,X05,DI-05,0,
/// </summary>
public static string OutCheck = "OutCheck";
/// <summary>
/// DO,运行状态指示灯,AutoRun_HddLed,0,PRO_AOI_IP_1,0,运行状态指示灯,Y01,DO-01,0,
/// </summary>
public static string AutoRun_HddLed = "AutoRun_HddLed";
/// <summary>
/// DO,线体驱动电机运转,Line_Run,1,PRO_AOI_IP_1,0,线体驱动电机运转,Y02,DO-02,0,
/// </summary>
public static string Line_Run = "Line_Run";
/// <summary>
/// DO,进料线阻挡下降,StopDown,2,PRO_AOI_IP_1,0,进料线阻挡下降,Y03,DI-03,0,
/// </summary>
public static string StopDown = "StopDown";
/// <summary>
/// DO,进料线出口阻挡下降,OutStopDown,3,PRO_AOI_IP_1,0,进料线出口阻挡下降,Y04,DI-04,0,
/// </summary>
public static string OutStopDown = "OutStopDown";
}
public enum IO_VALUE
{
/// <summary>
/// 低位
/// </summary>
LOW = 0,
/// <summary>
/// 高位
/// </summary>
HIGH = 1,
}
}
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class RobotConfig
{
public static Dictionary<string, string> ProIOIpMap = null;
public const string IOIP_Str = "PRO_AOI_IP";
public static readonly ILog LOGGER = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 编号,与服务器通信的唯一标识
/// </summary>
public string CID { get; set; }
/// <summary>
/// 料层类型
/// </summary>
public string StoreType { get; set; }
/// <summary>
/// 配置文件路径
/// </summary>
public string ConfigFilePath { get; set; }
/// <summary>
/// 输入IO配置
/// 手动VMI流水线输入Io列表,key=对应的坐标位置的positionNum
/// </summary>
public Dictionary<String, ConfigIO> StoreDIList { get; set; }
/// <summary>
/// 输出IO配置
/// 手动VMI流水线输出Io列表,key=对应的坐标位置的positionNum
/// </summary>
public Dictionary<String, ConfigIO> StoreDOList { get; set; }
/// <summary>
/// VMI流水线所有用到的IO卡名称
/// </summary>
public List<string> DIODeviceNameList { get; set; }
/// <summary>
/// VMI流水线所有用到的运动卡名称
/// </summary>
public List<string> SMCDeviceNameList { get; set; }
/// <summary>
/// 必须拥有的DI列表
/// </summary>
protected List<string> MustHaveDIList { get; set; }
/// <summary>
/// 必须拥有的DO列表
/// </summary>
protected List<string> MustHaveDOList { get; set; }
protected virtual void initMustHavePro()
{
MustHaveDIList = new List<string>();
MustHaveDOList = new List<string>();
}
public RobotConfig()
{
initMustHavePro();
}
public RobotConfig(int id, string cid, string type, string filepath)
{
initMustHavePro();
MustHaveDIList = new List<string>();
MustHaveDOList = new List<string>();
this.Id = id;
this.CID = cid;
this.StoreType = type;
this.ConfigFilePath = filepath;
}
public virtual void LoadConfig(List<ConfigBase> configList)
{
StoreDIList = new Dictionary<string, ConfigIO>();
StoreDOList = new Dictionary<string, ConfigIO>();
DIODeviceNameList = new List<string>();
SMCDeviceNameList = new List<string>();
//取得属性集合
PropertyInfo[] props = GetType().GetProperties();
Dictionary<string, string> proMap = CSVReaderBase.getConfigProAttributeMap(GetType());
List<string> checkProList = new List<string>(proMap.Keys);//用来检测attribute属性都应该要配置值
foreach (ConfigBase con in configList)
{
if (con.ProType == ConfigItemType.AXIS || con.ProType == ConfigItemType.PRO)
{
if (proMap.ContainsKey(con.ProName))
{
string proName = proMap[con.ProName];
checkProList.Remove(con.ProName);
PropertyInfo prop = props.First(c => c.Name == proName);//获取同名属性
if (prop != null)
{
if (con.ProType == ConfigItemType.AXIS)
{
//如果属性存在
prop.SetValue(this, Convert.ChangeType(con, prop.PropertyType), null);//赋值****在这里需要考虑类型问题
ConfigMoveAxis axis = (ConfigMoveAxis)con;
if (!SMCDeviceNameList.Contains(axis.DeviceName) && axis.GetAxisValue() >= 0)
{
SMCDeviceNameList.Add(axis.DeviceName);
}
}
else if (con.ProType == ConfigItemType.PRO)
{
prop.SetValue(this, Convert.ChangeType(con.ProValue, prop.PropertyType), null);//赋值
}
}
else
{
LOGGER.Error("配置文件:" + this.ConfigFilePath + ",属性名=" + con.ProName + "的属性未找到匹配字段!");
}
}
else if (!ProIOIpMap.ContainsKey(con.ProName) && con.ProName.ToUpper().Contains(IOIP_Str))
{
ProIOIpMap.Add(con.ProName, con.ProValue);
if (!DIODeviceNameList.Contains(con.ProValue))
{
DIODeviceNameList.Add(con.ProValue);
}
}
else
{
LOGGER.Error("配置文件:" + this.ConfigFilePath + ",属性名=" + con.ProName + "的属性未找到匹配字段!");
}
}
else if (con.ProType == ConfigItemType.DI)
{
if (IO_Type.GetTypeList().Contains(con.ProName))
{
ConfigIO io = (ConfigIO)con;
if (!DIODeviceNameList.Contains(io.DeviceName) && (io.GetIOAddr() >= 0 || io.GetIOAddr() >= 0)&&io.DeviceName.Contains(IOIP_Str).Equals(false))
{
DIODeviceNameList.Add(io.DeviceName);
}
this.StoreDIList.Add(con.ProName, io);
}
else
{
LOGGER.Error("配置文件:" + this.ConfigFilePath + ",属性名=" + con.ProName + "的属性未找到匹配字段!");
}
}
else if (con.ProType == ConfigItemType.DO)
{
if (IO_Type.GetTypeList().Contains(con.ProName))
{
ConfigIO io = (ConfigIO)con;
if (!DIODeviceNameList.Contains(io.DeviceName) && io.GetIOAddr() >= 0 && io.DeviceName.Contains(IOIP_Str).Equals(false))
{
DIODeviceNameList.Add(io.DeviceName);
}
this.StoreDOList.Add(con.ProName, io);
}
else
{
LOGGER.Error("配置文件:" + this.ConfigFilePath + ",属性名=" + con.ProName + "的属性未找到匹配字段!");
}
}
}
if (checkProList.Count >= 0)
{
//常规属性检测
foreach (string str in checkProList)
{
PropertyInfo prop = props.First(c => c.Name == str);//获取同名属性
//判断是否必须要配置
object[] array = prop.GetCustomAttributes(false);
if (array.Length > 0)
{
ConfigProAttribute att = (ConfigProAttribute)array[0];
if (att != null)
{
if (att.IsMust)
{
throw new CVSFieldNotMatchingExection(this.ToString() + "的属性" + str + "必须配置值!");
}
else
{
if (prop.PropertyType.Equals(typeof(int)))
{
prop.SetValue(this, Convert.ChangeType(0, prop.PropertyType), null);//赋值****在这里需要考虑类型问题
}
else
{
prop.SetValue(this, Convert.ChangeType("", prop.PropertyType), null);//赋值****在这里需要考虑类型问题
}
}
}
}
}
//DI检测
foreach (string di in MustHaveDIList)
{
if (!StoreDIList.ContainsKey(di))
{
throw new CVSFieldNotMatchingExection(this.ToString() + "的DI属性" + di + "必须配置值!");
}
}
//DO检测
foreach (string io in MustHaveDOList)
{
if (!this.StoreDOList.ContainsKey(io))
{
throw new CVSFieldNotMatchingExection(this.ToString() + "的DO属性" + io + "必须配置值!");
}
}
}
}
public ConfigIO getWaitIO(string ioType)
{
if (StoreDIList.ContainsKey(ioType))
{
return StoreDIList[ioType];
}
else if (StoreDOList.ContainsKey(ioType))
{
return StoreDOList[ioType];
}
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnlineStore.LoadCSVLibrary
{
public class LineConfig : RobotConfig
{
public LineConfig()
: base()
{
}
public LineConfig( string filepath)
: base(1, "", "", filepath)
{
}
/// <summary>
/// PRO,休眠秒数(秒),SleepSeconds,180,,,,,,,
/// </summary>
[ConfigProAttribute("SleepSeconds", false)]
public int SleepSeconds { get; set; }
/// <summary>
/// PRO IO信号超时时间(毫秒) IOSingle_TimerOut 5000
/// </summary>
[ConfigProAttribute("IOSingle_TimerOut", false)]
public int IOSingle_TimerOut { get; set; }
/// <summary>
/// PRO IO模块对应的DI数量 IO_DILength 192.168.200.10#16;192.168.200.11#4
/// </summary>
[ConfigProAttribute("IO_DILength")]
public string IO_DILength { get; set; }
/// <summary>
/// PRO 模块对应的DO数量 IO_DOLength 192.168.200.10#16;192.168.200.11#4
/// </summary>
[ConfigProAttribute("IO_DOLength")]
public string IO_DOLength { get; set; }
/// <summary>
///PRO,线体入口节点名称,In_AgvName,A2,,,,,,,
/// </summary>
[ConfigProAttribute("In_AgvName")]
public string In_AgvName { get; set; }
/// <summary>
/// PRO,线体出口节点名称,Out_AgvName,A1,,,,,,,
/// </summary>
[ConfigProAttribute("Out_AgvName")]
public string Out_AgvName { get; set; }
public double AirCheckSeconds = 60;
/// <summary>
///PRO,L2线入口RFIDIP,L2_In_RFIDIP,192.168.103.108,,,,,, ,
/// </summary>
[ConfigProAttribute("L2_In_RFIDIP", false)]
public string L2_In_RFIDIP { get; set; }
/// <summary>
/// PRO,L2线出口RFIDIP,L2_Out_RFIDIP,192.168.103.107,,,,,, ,
/// </summary>
[ConfigProAttribute("L2_Out_RFIDIP", false)]
public string L2_Out_RFIDIP { get; set; }
protected override void initMustHavePro()
{
MustHaveDIList = new List<string>();
MustHaveDOList = new List<string>();
MustHaveDIList.Add(IO_Type.SuddenStop_BTN);
MustHaveDIList.Add(IO_Type.Reset_BTN);
MustHaveDOList.Add(IO_Type.AutoRun_HddLed);
//MustHaveDOList.Add(IO_Type.Alarm_HddLed);
}
private Dictionary<string, ushort> DILengthMap = null;
private Dictionary<string, ushort> DOLengthMap = null;
public ushort GetDILength(string ip)
{
try
{
if (DILengthMap == null)
{
DILengthMap = new Dictionary<string, ushort>();
string[] arrayList = IO_DILength.Split(';');
foreach (string str in arrayList)
{
string[] arrStr = str.Split('#');
if (arrStr.Length == 2)
{
string ioip = arrStr[0];
ushort length = Convert.ToUInt16(arrStr[1]);
DILengthMap.Add(ioip, length);
}
}
}
}
catch (Exception ex)
{
}
if (DILengthMap.ContainsKey(ip))
{
return DILengthMap[ip];
}
return 16;
}
public ushort GetDOLength(string ip)
{
try
{
if (DOLengthMap == null)
{
DOLengthMap = new Dictionary<string, ushort>();
string[] arrayList = IO_DOLength.Split(';');
foreach (string str in arrayList)
{
string[] arrStr = str.Split('#');
if (arrStr.Length == 2)
{
string ioip = arrStr[0];
ushort length = Convert.ToUInt16(arrStr[1]);
DOLengthMap.Add(ioip, length);
}
}
}
}
catch (Exception ex)
{
}
if (DOLengthMap.ContainsKey(ip))
{
return DOLengthMap[ip];
}
return 16;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{064BEBF5-8FAA-4EA2-A5F3-A06E6E7D9251}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OnlineStore.LoadCSVLibrary</RootNamespace>
<AssemblyName>LoadCSVLibrary</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\dll\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSVExection.cs" />
<Compile Include="Config\ConfigItemBase.cs" />
<Compile Include="Config\ConfigProAttribute.cs" />
<Compile Include="Config\bean\VMLLineConfig.cs" />
<Compile Include="Config\bean\IO_Type.cs" />
<Compile Include="CSVAttribute.cs" />
<Compile Include="Config\CSVConfigReader.cs" />
<Compile Include="CSVReaderBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Config\bean\RobotConfig.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj">
<Project>{43cdd09e-fcf3-4960-a01d-3bbfe9933122}</Project>
<Name>Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file \ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("LoadCVSLibrary")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LoadCVSLibrary")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("f9998ad1-83a5-4191-8109-7e255e71744e")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
namespace UserFromControl
{
partial class IOTextControl
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.pictureBox2 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
this.SuspendLayout();
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(30, 4);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(53, 12);
this.label1.TabIndex = 0;
this.label1.Text = "测试一下";
//
// pictureBox1
//
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(25, 27);
this.pictureBox1.TabIndex = 1;
this.pictureBox1.TabStop = false;
this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click);
//
// pictureBox2
//
this.pictureBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.pictureBox2.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.pictureBox2.Location = new System.Drawing.Point(0, 0);
this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(25, 27);
this.pictureBox2.TabIndex = 2;
this.pictureBox2.TabStop = false;
this.pictureBox2.Click += new System.EventHandler(this.pictureBox2_Click);
//
// IOTextControl
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.Controls.Add(this.pictureBox2);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.label1);
this.Name = "IOTextControl";
this.Size = new System.Drawing.Size(202, 27);
this.Load += new System.EventHandler(this.IOStatusControl_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.PictureBox pictureBox2;
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace UserFromControl
{
public partial class IOTextControl : UserControl
{
public string IOName { get; set; }
public int IOValue { get; set; }
public Boolean isCanClick { get; set; }
public IOTextControl()
{
InitializeComponent();
if (ImageManager.IsInit==false)
{
ImageManager.Init();
}
this.pictureBox1.BackgroundImage = ImageManager.imgGrey;
this.pictureBox2.BackgroundImage = ImageManager.imgGreen;
pictureBox1.Visible = true;
pictureBox2.Visible = false;
isCanClick = false;
}
public IOTextControl(string ioName, string name, int widht = 220, int height = 25, int ioValue = 0, bool canClick = false, int tabIndex = 0)
{
InitializeComponent();
if (ImageManager.IsInit == false)
{
ImageManager.Init();
}
this.pictureBox1.BackgroundImage = ImageManager.imgGrey;
this.pictureBox2.BackgroundImage = ImageManager.imgGreen;
pictureBox1.Visible = true;
pictureBox2.Visible = false;
isCanClick = false;
IOName = ioName;
IOValue = IOValue;
isCanClick = canClick;
Name = "IO_" + name;
Size = new System.Drawing.Size(widht, height);
TabIndex = tabIndex;
}
public void ShowData()
{
label1.Text = IOName;
if (IOValue == 0)
{
pictureBox1.Visible = true;
pictureBox2.Visible = false;
}
else
{
pictureBox1.Visible = false;
pictureBox2.Visible = true;
}
}
private void IOStatusControl_Load(object sender, EventArgs e)
{
ShowData();
}
private void pictureBox2_Click(object sender, EventArgs e)
{
if (isCanClick)
{
pictureBox2.Visible = true;
pictureBox1.Visible = false;
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
if (isCanClick)
{
pictureBox2.Visible = false;
pictureBox1.Visible = true;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace UserFromControl
{
public class ImageManager
{
public static Image imgGrey;
public static Image imgGreen;
/// <summary>
/// 是否已经初始化过了
/// </summary>
public static bool IsInit = false;
public static void Init()
{
try
{
IsInit = true;
imgGrey = Image.FromFile(Application.StartupPath + "\\image\\gray2.png");
imgGreen = Image.FromFile(Application.StartupPath+"\\image\\green.png");
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("UserFromControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UserFromControl")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("a6a898b1-9dd0-4815-91c5-11c79ea72550")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace UserFromControl.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UserFromControl.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F018462A-D9BC-4365-97F2-F6D71751641E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UserFromControl</RootNamespace>
<AssemblyName>UserFromControl</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ImageManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="IOTextControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="IOTextControl.Designer.cs">
<DependentUpon>IOTextControl.cs</DependentUpon>
</Compile>
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="IOTextControl.resx">
<DependentUpon>IOTextControl.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="image\gray.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="image\gray1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="image\gray2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="image\green.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="image\green1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file \ No newline at end of file
文件属性发生变化
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!