├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── KeyencePLC.sln
├── KeyencePLC
├── App.config
├── App.xaml
├── App.xaml.cs
├── KeyencePLC.csproj
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── PLC.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── WebPage
│ ├── Demo.html
│ └── WebAdaptor.cs
├── packages.config
└── readme.txt
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/KeyencePLC.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyencePLC", "KeyencePLC\KeyencePLC.csproj", "{2C254479-FEAA-46E8-8768-C0913DFCFAF3}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {2C254479-FEAA-46E8-8768-C0913DFCFAF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {2C254479-FEAA-46E8-8768-C0913DFCFAF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {2C254479-FEAA-46E8-8768-C0913DFCFAF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {2C254479-FEAA-46E8-8768-C0913DFCFAF3}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {CDEBD60C-D4DB-4D11-BCC3-E6484B7C41C1}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/KeyencePLC/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/KeyencePLC/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/KeyencePLC/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace KeyencePLC
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/KeyencePLC/KeyencePLC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2C254479-FEAA-46E8-8768-C0913DFCFAF3}
8 | WinExe
9 | KeyencePLC
10 | KeyencePLC
11 | v4.5
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\HslCommunication.5.2.1\lib\net35\HslCommunication.dll
38 |
39 |
40 | C:\Users\admin\Desktop\Rubber_Sucker_Assemble (3)\packages\MahApps.Metro.1.6.5\lib\net40\MahApps.Metro.dll
41 |
42 |
43 | ..\packages\MaterialDesignColors.1.1.2\lib\net45\MaterialDesignColors.dll
44 |
45 |
46 | ..\packages\MaterialDesignThemes.2.4.1.1101\lib\net45\MaterialDesignThemes.Wpf.dll
47 |
48 |
49 | ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | 4.0
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | MSBuild:Compile
72 | Designer
73 |
74 |
75 |
76 | MSBuild:Compile
77 | Designer
78 |
79 |
80 | App.xaml
81 | Code
82 |
83 |
84 | MainWindow.xaml
85 | Code
86 |
87 |
88 |
89 |
90 |
91 | Code
92 |
93 |
94 | True
95 | True
96 | Resources.resx
97 |
98 |
99 | True
100 | Settings.settings
101 | True
102 |
103 |
104 | ResXFileCodeGenerator
105 | Resources.Designer.cs
106 |
107 |
108 |
109 | SettingsSingleFileGenerator
110 | Settings.Designer.cs
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/KeyencePLC/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/KeyencePLC/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using HslCommunication.LogNet;
2 | using KeyencePLC.Properties;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Drawing;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Net;
9 | using System.Net.Sockets;
10 | using System.Text;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using System.Windows.Data;
16 | using System.Windows.Documents;
17 | using System.Windows.Input;
18 | using System.Windows.Media;
19 | using System.Windows.Media.Imaging;
20 | using System.Windows.Navigation;
21 | using System.Windows.Shapes;
22 | using static KeyencePLC.PLC;
23 |
24 | namespace KeyencePLC
25 | {
26 | ///
27 | /// MainWindow.xaml 的交互逻辑
28 | ///
29 | public partial class MainWindow : Window
30 | {
31 | #region 本地变量
32 |
33 | // The main control for communicating through the telnet port
34 | private Socket socket;
35 | private short[] parsedata = new short[10];
36 | protected bool sw_ugoahead;
37 | protected bool sw_igoahead;
38 | protected bool sw_echo;
39 | protected bool sw_termsent;
40 |
41 | private ILogNet logNet = new LogNetSingle(Application.ResourceAssembly + "\\Logs\\Log.txt");
42 |
43 |
44 |
45 | // Various colors for logging info
46 | private System.Drawing.Color[] LogMsgTypeColor = { System.Drawing.Color.Blue, System.Drawing.Color.Green, System.Drawing.Color.Black, System.Drawing.Color.Orange, System.Drawing.Color.Red, System.Drawing.Color.OrangeRed };
47 |
48 | // Temp holder for whether a key was pressed
49 | private bool KeyHandled = false;
50 |
51 | private int checkPrint;
52 |
53 |
54 | #endregion
55 |
56 |
57 | public MainWindow()
58 | {
59 | InitializeComponent();
60 | System.Timers.Timer t = new System.Timers.Timer(100);//实例化Timer类,设置间隔时间为100毫秒;
61 | t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件;
62 | t.AutoReset = true;//设置是执行一次(false)还是一直执行(true);
63 | t.Enabled = true; //是否执行System.Timers.Timer.Elapsed事件; ,调用start()方法也可以将其设置为true
64 |
65 |
66 | // Restore the users settings
67 | InitializeControlValues();
68 |
69 | //WebBrowserDemo.Navigate(new Uri("www.baidu.com"));
70 | WebBrowserNet.Navigate(new Uri(Directory.GetCurrentDirectory()+"/WebPage/Demo.html"));
71 |
72 | // Enable/disable controls based on the current state
73 | EnableControls();
74 |
75 | IPAddress[] AddressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;
76 |
77 | string ip = AddressList[0].ToString();
78 |
79 | if (ip != "")
80 | {
81 | this.sbpLocalIP.Content = "本地IP地址:" + ip;
82 | }
83 | else
84 | {
85 | this.sbpStatus.Content = "无法获得本机IP地址,请检查网络连接";
86 | }
87 |
88 | }
89 |
90 | public void theout(object source, System.Timers.ElapsedEventArgs e)
91 | {
92 | this.textBoxReceive.Dispatcher.Invoke(
93 | new Action(
94 | delegate
95 | {
96 | string str = Receive();
97 | this.textBoxReceive.Text = str;
98 | Log(LogMsgType.Incoming, str);
99 |
100 | }
101 | )
102 |
103 | );
104 | //Dispatcher.BeginInvoke(
105 | // new Action(
106 | // delegate
107 | // {
108 | // string str = Receive();
109 | // this.textBoxReceive.Text = str;
110 | // Paragraph paragraphText = new Paragraph();
111 | // paragraphText.Inlines.Add(str);
112 | // this.rtbText.Document.Blocks.Add(paragraphText);
113 | // }
114 | // )
115 | // );
116 | // rtbConsole.Dispatcher.Invoke(
117 | //new Action(
118 | // delegate
119 | // {
120 | // string str = Receive();
121 | // Log(LogMsgType.Incoming, str);
122 | // }
123 | // )
124 | //);
125 |
126 | }
127 |
128 | //public Showtext(object source,System.Timers.ElapsedEventArgs e)
129 | //{
130 | // this.Dispatcher.Invoke(
131 | // new Action(
132 | // delegate
133 | // {
134 | // string str;
135 | // str = Receive();
136 | // return str;
137 | // })
138 |
139 | // );
140 |
141 | //}
142 |
143 |
144 |
145 |
146 | //public void DragWindow(object sender, MouseButtonEventArgs args)
147 | //{
148 | // this.DragMove();
149 | //}
150 |
151 | //public void CloseWindow(object sender, RoutedEventArgs args)
152 | //{
153 | // this.Close();
154 | //}
155 |
156 | /// Enable/disable controls based on the app's current state.
157 | private void EnableControls()
158 | {
159 | // Enable/disable controls based on whether the port is open or not
160 | gbPortSettings.IsEnabled = !socket.Connected;
161 | //gbCustomBtn.Enabled = socket.Connected;
162 |
163 | txtSendData.IsEnabled = btnSend.IsEnabled = socket.Connected;
164 | try
165 | {
166 | if (socket.Connected)
167 | {
168 | btnOpenPort.Content = "&关闭端口";
169 | }
170 | else
171 | {
172 | btnOpenPort.Content = "&打开端口";
173 |
174 |
175 | }
176 | }
177 | catch (Exception e)
178 | {
179 | MessageBox.Show(e.ToString());
180 | }
181 |
182 | }
183 |
184 | private void SendData()
185 | {
186 | if (CurrentDataMode == DataMode.Text)
187 | {
188 | // Send the user's text straight out the port
189 | SocketSend(txtSendData.Text);
190 |
191 | // Show in the terminal window the user's text
192 | //Log(LogMsgType.Outgoing, txtSendData.Text + "\n");
193 | }
194 | else
195 | {
196 | try
197 | {
198 | // Convert the user's string of hex digits (ex: B4 CA E2) to a byte array
199 | byte[] data = HexStringToByteArray(txtSendData.Text);
200 |
201 | // Send the binary data out the port
202 | SocketSend(data);
203 |
204 | // Show the hex digits on in the terminal window
205 | //Log(LogMsgType.Outgoing, ByteArrayToHexString(data) + "\n");
206 | }
207 | catch (FormatException)
208 | {
209 | // Inform the user if the hex string was not properly formatted
210 | //Log(LogMsgType.Error, "Not properly formatted hex string: " + txtSendData.Text + "\n");
211 | }
212 | }
213 | txtSendData.SelectAll();
214 | }
215 |
216 | /// Save the user's settings.
217 | private void SaveSettings()
218 | {
219 | Settings.Default.HostIP = txtRemoteAddress.Text;
220 | Settings.Default.Port = txtPort.Text;
221 | Settings.Default.DataMode = CurrentDataMode;
222 | Settings.Default.Save();
223 | }
224 |
225 |
226 | //private void loadAutomationButtonGroupConfig()
227 | //{
228 | // FileStream stream = new FileStream("Telnet.xml", FileMode.Open);
229 | // //XmlSerializer serializer = new XmlSerializer(typeof(buttonItemCollection));
230 | // //this.btnItems = (buttonItemCollection)serializer.Deserialize(stream);
231 |
232 | // //foreach (buttonItem item in this.btnItems.buttonItems)
233 | // //{
234 | // // int index = item.buttonID - 1;
235 | // // if (index < this.automationButtonGroup.Length)
236 | // // {
237 | // // Button button = this.automationButtonGroup[index];
238 | // // button.Text = item.buttonTitle;
239 | // // Font font = new Font(this.btn1.Font.FontFamily, this.btn1.Font.Size, this.btn1.Font.Style);
240 | // // SizeF ef = button.CreateGraphics().MeasureString(" " + item.buttonTitle + " ", font, (SizeF)this.btn1.Size);
241 | // // button.Width = ((int)ef.Width) * 4;
242 | // // }
243 | // //}
244 | // stream.Close();
245 | //}
246 | /// Populate the form's controls with default settings.
247 | private void InitializeControlValues()
248 | {
249 | //this.automationButtonGroup = new Button[] { this.btn1, this.btn2, this.btn3, this.btn4, this.btn5, this.btn6, this.btn7, this.btn8 };
250 |
251 | txtRemoteAddress.Text = Settings.Default.HostIP;
252 | txtPort.Text = Settings.Default.Port.ToString();
253 | CurrentDataMode = Settings.Default.DataMode;
254 |
255 | try
256 | {
257 | //this.loadAutomationButtonGroupConfig();
258 | }
259 | catch (Exception exception)
260 | {
261 | MessageBox.Show("Automation XML file parser error. Details:" + exception.Message, "automation XML parser error", MessageBoxButton.OK, MessageBoxImage.Hand);
262 | //base.Close();
263 | }
264 |
265 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
266 | socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
267 |
268 | }
269 |
270 |
271 |
272 | /// Log data to the terminal window.
273 | /// The type of message to be written.
274 | /// The string containing the message to be shown.
275 | private void Log(LogMsgType msgtype, string msg)
276 | {
277 | switch (msgtype)
278 | {
279 | default:
280 | case LogMsgType.Copyright:
281 | rtbConsole.Dispatcher.Invoke(new Action(delegate
282 | {
283 |
284 | rtbConsole.AppendText(msg);
285 | }));
286 | break;
287 | case LogMsgType.Outgoing:
288 | rtbConsole.Dispatcher.Invoke(new Action(delegate
289 | {
290 | rtbConsole.AppendText(DateTime.Now.ToLongTimeString());
291 | rtbConsole.AppendText(" Tx:");
292 | rtbConsole.AppendText(msg);
293 |
294 | }));
295 | break;
296 | case LogMsgType.Incoming:
297 | rtbConsole.Dispatcher.Invoke(new Action(delegate
298 | {
299 | rtbConsole.AppendText(DateTime.Now.ToLongTimeString());
300 | rtbConsole.AppendText(" Rx:");
301 | rtbConsole.AppendText(msg);
302 | rtbConsole.AppendText("\n");
303 | }));
304 | break;
305 |
306 |
307 | //case LogMsgType.Copyright:
308 | // rtbConsole.Dispatcher.BeginInvoke(new EventHandler(delegate
309 | // {
310 | // rtbConsole.SelectedText = string.Empty;
311 | // rtbConsole.SelectionFont = new Font(rtbConsole.SelectionFont, System.Drawing.FontStyle.Bold);
312 | // rtbConsole.SelectionColor = LogMsgTypeColor[(int)msgtype];
313 | // rtbConsole.AppendText(msg);
314 | // rtbConsole.ScrollToCaret();
315 | // }));
316 | // break;
317 | //case LogMsgType.Outgoing:
318 | // rtbConsole.Dispatcher.BeginInvoke(new EventHandler(delegate
319 | // {
320 | // rtbConsole.SelectedText = string.Empty;
321 | // rtbConsole.SelectionFont = new Font(rtbConsole.SelectionFont, System.Drawing.FontStyle.Bold);
322 | // rtbConsole.SelectionColor = LogMsgTypeColor[(int)msgtype];
323 | // rtbConsole.AppendText(DateTime.Now.ToLongTimeString());
324 | // rtbConsole.AppendText(" Tx:");
325 | // rtbConsole.AppendText(msg);
326 | // rtbConsole.ScrollToCaret();
327 | // }));
328 | // break;
329 | //case LogMsgType.Incoming:
330 | // rtbConsole.Dispatcher.BeginInvoke(new EventHandler(delegate
331 | // {
332 | // rtbConsole.SelectedText = string.Empty;
333 | // rtbConsole.SelectionFont = new Font(rtbConsole.SelectionFont, System.Drawing.FontStyle.Bold);
334 | // rtbConsole.SelectionColor = LogMsgTypeColor[(int)msgtype];
335 | // rtbConsole.AppendText(DateTime.Now.ToLongTimeString());
336 | // rtbConsole.AppendText(" Rx:");
337 | // rtbConsole.AppendText(msg);
338 | // rtbConsole.AppendText("\n");
339 | // rtbConsole.ScrollToCaret();
340 | // }));
341 | // break;
342 | }
343 |
344 | }
345 |
346 |
347 | #region
348 | /// Convert a string of hex digits (ex: E4 CA B2) to a byte array.
349 | /// The string containing the hex digits (with or without spaces).
350 | /// Returns an array of bytes.
351 | private byte[] HexStringToByteArray(string s)
352 | {
353 | s = s.Replace(" ", "");
354 | byte[] buffer = new byte[s.Length / 2];
355 | for (int i = 0; i < s.Length; i += 2)
356 | {
357 | buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
358 | }
359 |
360 | return buffer;
361 | }
362 |
363 | /// Converts an array of bytes into a formatted string of hex digits (ex: E4 CA B2)
364 | /// The array of bytes to be translated into a string of hex digits.
365 | /// Returns a well formatted string of hex digits with spacing.
366 | private string ByteArrayToHexString(byte[] data)
367 | {
368 | StringBuilder sb = new StringBuilder(data.Length * 3);
369 | foreach (byte b in data)
370 | {
371 | sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
372 | }
373 |
374 | return sb.ToString().ToUpper();
375 | }
376 |
377 | ///
378 | /// 将一条十六进制字符串转换为ASCII
379 | ///
380 | /// 一条十六进制字符串
381 | /// 返回一条ASCII码
382 | public static string HexStringToASCII(string hexstring)
383 | {
384 | byte[] bt = HexStringToBinary(hexstring);
385 | string lin = "";
386 | for (int i = 0; i < bt.Length; i++)
387 | {
388 | lin = lin + bt[i] + " ";
389 | }
390 |
391 |
392 | string[] ss = lin.Trim().Split(new char[] { ' ' });
393 | char[] c = new char[ss.Length];
394 | int a;
395 | for (int i = 0; i < c.Length; i++)
396 | {
397 | a = Convert.ToInt32(ss[i]);
398 | c[i] = Convert.ToChar(a);
399 | }
400 |
401 | string b = new string(c);
402 | return b;
403 | }
404 |
405 |
406 | /**/
407 | ///
408 | /// 16进制字符串转换为二进制数组
409 | ///
410 | /// 用空格切割字符串
411 | /// 返回一个二进制字符串
412 | public static byte[] HexStringToBinary(string hexstring)
413 | {
414 |
415 | string[] tmpary = hexstring.Trim().Split(' ');
416 | byte[] buff = new byte[tmpary.Length];
417 | for (int i = 0; i < buff.Length; i++)
418 | {
419 | buff[i] = Convert.ToByte(tmpary[i], 16);
420 | }
421 | return buff;
422 | }
423 |
424 | #endregion
425 |
426 | #region Socket
427 | //向Telnet服务器发送命令
428 | private void SocketSend(string msg)
429 | {
430 | System.Byte[] message = System.Text.Encoding.ASCII.GetBytes(msg.ToCharArray());
431 | socket.Send(message, message.Length, 0);
432 | }
433 |
434 | //向Telnet服务器发送命令
435 | private void SocketSend(char[] chr)
436 | {
437 | System.Byte[] message = System.Text.Encoding.ASCII.GetBytes(chr);
438 | socket.Send(message, message.Length, 0);
439 | }
440 |
441 | //向Telnet服务器发送数据
442 | private void SocketSend(byte[] data)
443 | {
444 | System.Byte[] message = data;
445 | socket.Send(message, message.Length, 0);
446 | }
447 |
448 | //接收数据
449 | private string Receive()
450 | {
451 | //用于接收数据的缓冲
452 | byte[] buf;
453 | string result = "";
454 |
455 | int count = socket.Available;
456 | if (count > 0)
457 | {
458 | buf = new byte[count];
459 | socket.Receive(buf);
460 | if (CurrentDataMode == DataMode.Hex)
461 | {
462 | result = ByteArrayToHexString(buf);
463 | //MessageBox.Show(result);
464 | textBoxReceive.Text = result;
465 | }
466 | else
467 | {
468 | result = ProcessOptions(buf);
469 | //MessageBox.Show(result);
470 | textBoxReceive.Text = result;
471 | }
472 | }
473 |
474 | return result;
475 | }
476 | #region
477 | #if false
478 | //处理命令字符,buf是包含数据的缓冲
479 | private string ProcessOptions(byte[] buf)
480 | {
481 | string strNormal = "";
482 | int i = 0;
483 | while (i < buf.Length)
484 | {
485 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
486 | i++;
487 | }
488 | return strNormal;
489 | }
490 | #else
491 | #region 常量
492 | const char GO_NORM = (char)0;
493 | const char SUSP = (char)237;
494 |
495 | const char ABORT = (char)238;
496 | const char SE = (char)240; //子选项结束Subnegotiation End
497 | const char NOP = (char)241;
498 | const char DM = (char)242; //Data Mark
499 | const char BREAK = (char)243; //BREAK
500 | const char IP = (char)244; //Interrupt Process
501 | const char AO = (char)245; //Abort Output
502 | const char AYT = (char)246; //Are you there
503 | const char EC = (char)247; //Erase character
504 | const char EL = (char)248; //Erase Line
505 | const char GOAHEAD = (char)249; //Go Ahead
506 | const char SB = (char)250; //子选项开始Subnegotiation Begin
507 |
508 | const char WILL = (char)251;
509 | const char WONT = (char)252;
510 | const char DO = (char)253;
511 | const char DONT = (char)254;
512 | const char IAC = (char)255;
513 |
514 | const char BINARY = (char)0;
515 | const char IS = (char)0;
516 | const char SEND = (char)1;
517 | const char ECHO = (char)1;
518 | const char RECONNECT = (char)2;
519 | const char SGA = (char)3;
520 | const char AMSN = (char)4;
521 | const char STATUS = (char)5;
522 | const char TIMING = (char)6;
523 | const char RCTAN = (char)7;
524 | const char OLW = (char)8;
525 | const char OPS = (char)9;
526 | const char OCRD = (char)10;
527 | const char OHTS = (char)11;
528 | const char OHTD = (char)12;
529 | const char OFFD = (char)13;
530 | const char OVTS = (char)14;
531 | const char OVTD = (char)15;
532 | const char OLFD = (char)16;
533 | const char XASCII = (char)17;
534 | const char LOGOUT = (char)18;
535 | const char BYTEM = (char)19;
536 | const char DET = (char)20;
537 | const char SUPDUP = (char)21;
538 | const char SUPDUPOUT = (char)22;
539 | const char SENDLOC = (char)23;
540 | const char TERMTYPE = (char)24;
541 |
542 | const char EOR = (char)25;
543 | const char TACACSUID = (char)26;
544 | const char OUTPUTMARK = (char)27;
545 | const char TERMLOCNUM = (char)28;
546 | const char REGIME3270 = (char)29;
547 | const char X3PAD = (char)30;
548 | const char NAWS = (char)31;
549 | const char TERMSPEED = (char)32;
550 | const char TFLOWCNTRL = (char)33;
551 | const char LINEMODE = (char)34;
552 | const char DISPLOC = (char)35;
553 |
554 | const char ENVIRON = (char)36;
555 | const char AUTHENTICATION = (char)37;
556 | const char UNKNOWN39 = (char)39;
557 | const char EXTENDED_OPTIONS_LIST = (char)255;
558 | const char RANDOM_LOSE = (char)256;
559 |
560 | const char CR = (char)13; //回车
561 | const char LF = (char)10; //换行
562 | const string BACK = "[P";
563 | #endregion
564 | //处理命令字符,buf是包含数据的缓冲
565 | private string ProcessOptions(byte[] buf)
566 | {
567 | string strNormal = "";
568 | int i = 0;
569 | while (i < buf.Length)
570 | {
571 | if (buf[i] == IAC)
572 | {
573 | switch ((char)buf[++i])
574 | {
575 | case DO:
576 | Console.Write("--------------接收到 DO ");
577 | ProcessDo(buf[++i]);
578 | break;
579 | case DONT:
580 | Console.Write("--------------接收到 DONT ");
581 | ProcessDont(buf[++i]);
582 | break;
583 | case WONT:
584 | Console.Write("--------------接收到 WONT ");
585 | ProcessWont(buf[++i]);
586 | break;
587 | case WILL:
588 | Console.Write("--------------接收到 WILL ");
589 | ProcessWill(buf[++i]);
590 | break;
591 | case IAC:
592 | //正常字符
593 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
594 | break;
595 | case SB:
596 | //子会话开始
597 | int j = 0;
598 | while (buf[++i] != SE)
599 | {
600 | parsedata[j++] = buf[i];
601 | }
602 | //子会话结束:
603 | switch ((char)parsedata[0])
604 | {
605 | case TERMTYPE:
606 | break;
607 | case TERMSPEED:
608 | if (parsedata[1] == 1)
609 | {
610 | Console.WriteLine("发送: SB TERMSPEED 57600,57600");
611 | SocketSend(IAC + SB + TERMSPEED + IS + "57600,57600" + IAC + SE);
612 | }
613 | break;
614 | }
615 | break;
616 | default:
617 | Console.WriteLine("无效的命令" + buf[1]);
618 | i++;
619 | break;
620 | };
621 | }
622 | else
623 | {
624 | //正常的文字
625 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
626 | }
627 | i++;
628 | }
629 | return strNormal;
630 | }
631 |
632 | private void ProcessDo(short ch)
633 | {
634 | //处理DO,以WILL或者WONT响应
635 | switch ((char)ch)
636 | {
637 | case BINARY:
638 | Console.WriteLine(BINARY);
639 | SocketSend(new char[] { IAC, WONT, BINARY });
640 | Console.WriteLine("发送: WONT BINARY");
641 | break;
642 | case ECHO:
643 | Console.WriteLine(ECHO);
644 | SocketSend(new char[] { IAC, WONT, ECHO });
645 | Console.WriteLine("发送: WONT ECHO");
646 | break;
647 | case SGA:
648 | Console.WriteLine(SGA);
649 | if (!sw_igoahead)
650 | {
651 | SocketSend(new char[] { IAC, WILL, SGA });
652 | Console.WriteLine("发送: WILL SGA");
653 | sw_igoahead = true;
654 | }
655 | else
656 | {
657 | Console.WriteLine("不发送响应");
658 | }
659 | break;
660 | case TERMSPEED:
661 | Console.WriteLine(TERMSPEED);
662 | SocketSend(new char[] { IAC, WILL, TERMSPEED });
663 | Console.WriteLine("发送: WILL TERMSPEED");
664 |
665 | SocketSend(IAC + SB + TERMSPEED + (char)0 + "57600,57600" +
666 | IAC + SE);
667 | Console.WriteLine("发送:SB TERMSPEED 57600");
668 | break;
669 | case TFLOWCNTRL:
670 | Console.WriteLine(TFLOWCNTRL);
671 | SocketSend(new char[] { IAC, WONT, TFLOWCNTRL });
672 | Console.WriteLine("发送: WONT TFLOWCNTRL");
673 | break;
674 | case LINEMODE:
675 | Console.WriteLine(LINEMODE);
676 | SocketSend(new char[] { IAC, WONT, LINEMODE });
677 | Console.WriteLine("发送: WONT LINEMODE");
678 | break;
679 | case STATUS:
680 | Console.WriteLine(STATUS);
681 | SocketSend(new char[] { IAC, WONT, STATUS });
682 | Console.WriteLine("发送: WONT STATUS");
683 | break;
684 | case TIMING:
685 | Console.WriteLine(TIMING);
686 | SocketSend(new char[] { IAC, WONT, TIMING });
687 | Console.WriteLine("发送: WONT TIMING");
688 | break;
689 | case DISPLOC:
690 | Console.WriteLine(DISPLOC);
691 | SocketSend(new char[] { IAC, WONT, DISPLOC });
692 | Console.WriteLine("发送: WONT DISPLOC");
693 | break;
694 | case ENVIRON:
695 | Console.WriteLine(ENVIRON);
696 | SocketSend(new char[] { IAC, WONT, ENVIRON });
697 | Console.WriteLine("发送: WONT ENVIRON");
698 | break;
699 | case UNKNOWN39:
700 | Console.WriteLine(UNKNOWN39);
701 | SocketSend(new char[] { IAC, WILL, UNKNOWN39 });
702 | Console.WriteLine("发送: WILL UNKNOWN39");
703 | break;
704 | case AUTHENTICATION:
705 | Console.WriteLine(AUTHENTICATION);
706 | SocketSend(new char[] { IAC, WONT, AUTHENTICATION });
707 | Console.WriteLine("发送: WONT AUTHENTICATION");
708 | Console.WriteLine("发送: SB AUTHENTICATION");
709 | SocketSend(IAC + SB + AUTHENTICATION + (char)0 + (char)0 + (char)0 + (char)0 + "" + IAC + SE);
710 | break;
711 | default:
712 | Console.WriteLine("未知的选项");
713 | break;
714 | }
715 | }
716 |
717 | //处理DONT
718 | private void ProcessDont(short ch)
719 | {
720 | switch ((char)ch)
721 | {
722 | case SE:
723 | Console.WriteLine(SE);
724 | Console.WriteLine("接收到: RECEIVED SE");
725 | break;
726 | case ECHO:
727 | Console.WriteLine(ECHO);
728 | if (!sw_echo)
729 | {
730 | sw_echo = true;
731 | SocketSend(new char[] { IAC, WONT, ECHO });
732 | Console.WriteLine("发送: WONT ECHO");
733 | }
734 | break;
735 | case SGA:
736 | Console.WriteLine(SGA);
737 | if (!sw_ugoahead)
738 | {
739 | SocketSend(new char[] { IAC, WONT, SGA });
740 | Console.WriteLine("发送: WONT SGA");
741 | sw_ugoahead = true;
742 | }
743 | break;
744 | case TERMSPEED:
745 | Console.WriteLine(TERMSPEED);
746 | SocketSend(new char[] { IAC, WONT, TERMSPEED });
747 | Console.WriteLine("发送: WONT TERMSPEED");
748 | break;
749 | case TFLOWCNTRL:
750 | Console.WriteLine(TFLOWCNTRL);
751 | SocketSend(new char[] { IAC, WONT, TFLOWCNTRL });
752 | Console.WriteLine("发送: WONT TFLOWCNTRL");
753 | break;
754 | case STATUS:
755 | Console.WriteLine(STATUS);
756 | SocketSend(new char[] { IAC, WONT, STATUS });
757 | Console.WriteLine("发送: WONT STATUS");
758 | break;
759 | case TIMING:
760 | Console.WriteLine(TIMING);
761 | SocketSend(new char[] { IAC, WONT, TIMING });
762 | Console.WriteLine("发送: WONT TIMING");
763 | break;
764 | case DISPLOC:
765 | Console.WriteLine(DISPLOC);
766 | SocketSend(new char[] { IAC, WONT, DISPLOC });
767 | Console.WriteLine("发送: WONT DISPLOC");
768 | break;
769 | case ENVIRON:
770 | Console.WriteLine(ENVIRON);
771 | SocketSend(new char[] { IAC, WONT, ENVIRON });
772 | Console.WriteLine("发送: WONT ENVIRON");
773 | break;
774 | case UNKNOWN39:
775 | Console.WriteLine(UNKNOWN39);
776 | SocketSend(new char[] { IAC, WILL, UNKNOWN39 });
777 | Console.WriteLine("发送: WILL UNKNOWN39");
778 | break;
779 | default:
780 | break;
781 | }
782 | }
783 |
784 | //处理WONT
785 | private void ProcessWont(short ch)
786 | {
787 | switch ((char)ch)
788 | {
789 | case ECHO:
790 | Console.WriteLine(ECHO);
791 | if (sw_echo)
792 | {
793 | sw_echo = false;
794 | SocketSend(new char[] { IAC, DONT, ECHO });
795 | Console.WriteLine("发送: DONT ECHO");
796 | }
797 | break;
798 | case SGA:
799 | Console.WriteLine(SGA);
800 | SocketSend(new char[] { IAC, DONT, SGA });
801 | Console.WriteLine("发送: DONT SGA");
802 | sw_igoahead = false;
803 | break;
804 | case TERMSPEED:
805 | Console.WriteLine(TERMSPEED);
806 | SocketSend(new char[] { IAC, DONT, TERMSPEED });
807 | Console.WriteLine("发送: DONT TERMSPEED");
808 | break;
809 | case TFLOWCNTRL:
810 | Console.WriteLine(TFLOWCNTRL);
811 | SocketSend(new char[] { IAC, DONT, TFLOWCNTRL });
812 | Console.WriteLine("发送: DONT TFLOWCNTRL");
813 | break;
814 | case LINEMODE:
815 | Console.WriteLine(LINEMODE);
816 | SocketSend(new char[] { IAC, DONT, LINEMODE });
817 | Console.WriteLine("发送: DONT LINEMODE");
818 | break;
819 | case STATUS:
820 | Console.WriteLine(STATUS);
821 | SocketSend(new char[] { IAC, DONT, STATUS });
822 | Console.WriteLine("发送: DONT STATUS");
823 | break;
824 | case TIMING:
825 | Console.WriteLine(TIMING);
826 | SocketSend(new char[] { IAC, WONT, TIMING });
827 | Console.WriteLine("发送: WONT TIMING");
828 | break;
829 | case DISPLOC:
830 | Console.WriteLine(DISPLOC);
831 | SocketSend(new char[] { IAC, DONT, DISPLOC });
832 | Console.WriteLine("发送: DONT DISPLOC");
833 | break;
834 | case ENVIRON:
835 | Console.WriteLine(ENVIRON);
836 | SocketSend(new char[] { IAC, DONT, ENVIRON });
837 | Console.WriteLine("发送: DONT ENVIRON");
838 | break;
839 | case UNKNOWN39:
840 | Console.WriteLine(UNKNOWN39);
841 | SocketSend(new char[] { IAC, DONT, UNKNOWN39 });
842 | Console.WriteLine("发送: DONT UNKNOWN39");
843 | break;
844 | default:
845 | Console.WriteLine("未知的选项");
846 | break;
847 | }
848 | }
849 |
850 | //处理WILL,以DO或者DONT响应
851 | private void ProcessWill(short ch)
852 | {
853 | switch ((char)ch)
854 | {
855 | case ECHO:
856 | Console.WriteLine(ECHO);
857 | if (!sw_echo)
858 | {
859 | sw_echo = true;
860 | SocketSend(new char[] { IAC, DO, ECHO });
861 | Console.WriteLine("发送: DO ECHO");
862 | }
863 | break;
864 | case SGA:
865 | Console.WriteLine(SGA);
866 | if (!sw_ugoahead)
867 | {
868 | SocketSend(new char[] { IAC, DO, SGA });
869 | Console.WriteLine("发送: DO SGA");
870 | sw_ugoahead = true;
871 | }
872 | else
873 | {
874 | Console.WriteLine("不发送响应");
875 | }
876 | break;
877 | case TERMTYPE:
878 | Console.WriteLine("TERMTYPE");
879 | if (!sw_termsent)
880 | {
881 | SocketSend(new char[] { IAC, WILL, TERMTYPE });
882 | SocketSend(IAC + SB + TERMTYPE + (char)0 + "VT100" + IAC + SE);
883 | sw_termsent = true;
884 | Console.WriteLine("发送: SB TERMTYPE VT100");
885 | }
886 | break;
887 | case TERMSPEED:
888 | Console.WriteLine(TERMSPEED);
889 | SocketSend(new char[] { IAC, DONT, TERMSPEED });
890 | Console.WriteLine("发送: DONT TERMSPEED");
891 | break;
892 | case TFLOWCNTRL:
893 | Console.WriteLine(TFLOWCNTRL);
894 | SocketSend(new char[] { IAC, DONT, TFLOWCNTRL });
895 | Console.WriteLine("发送: DONT TFLOWCNTRL");
896 | break;
897 | case LINEMODE:
898 | Console.WriteLine(LINEMODE);
899 | SocketSend(new char[] { IAC, WONT, LINEMODE });
900 | Console.WriteLine("发送: WONT LINEMODE");
901 | break;
902 | case STATUS:
903 | Console.WriteLine(STATUS);
904 | SocketSend(new char[] { IAC, DONT, STATUS });
905 | Console.WriteLine("发送: DONT STATUS");
906 | break;
907 | case TIMING:
908 | Console.WriteLine(TIMING);
909 | SocketSend(new char[] { IAC, DONT, TIMING });
910 | Console.WriteLine("发送: DONT TIMING");
911 | break;
912 | case DISPLOC:
913 | Console.WriteLine(DISPLOC);
914 | SocketSend(new char[] { IAC, DONT, DISPLOC });
915 | Console.WriteLine("发送: DONT DISPLOC");
916 | break;
917 | case ENVIRON:
918 | Console.WriteLine(ENVIRON);
919 | SocketSend(new char[] { IAC, DONT, ENVIRON });
920 | Console.WriteLine("发送: DONT ENVIRON");
921 | break;
922 | case UNKNOWN39:
923 | Console.WriteLine(UNKNOWN39);
924 | SocketSend(new char[] { IAC, DONT, UNKNOWN39 });
925 | Console.WriteLine("发送: DONT UNKNOWN39");
926 | break;
927 | default:
928 | Console.WriteLine("未知的选项");
929 | break;
930 | }
931 | }
932 | #endif
933 | #endregion
934 | private void TelnetThread()
935 | {
936 | while (socket.Connected)
937 | {
938 | try
939 | {
940 | string str = Receive();
941 | str = str.Replace("\0", "");
942 | string delim = "\b";
943 | str = str.Trim(delim.ToCharArray());
944 | if (str.Length > 0)
945 | {
946 | Console.WriteLine(str);
947 | //Dispatcher.BeginInvoke(
948 | // new Action(
949 | // delegate
950 | // {
951 | // this.textBoxReceive.Text = str;
952 | // Paragraph paragraphText = new Paragraph();
953 | // paragraphText.Inlines.Add(str);
954 | // this.rtbText.Document.Blocks.Add(paragraphText);
955 | // }
956 | // )
957 | // );
958 |
959 | //MessageBox.Show(str);
960 |
961 | if (str == OUTPUTMARK + BACK)
962 | {
963 | //BackupSpace键处理
964 | this.rtbConsole.IsReadOnly = false;
965 |
966 | this.rtbConsole.IsReadOnly = true;
967 | }
968 | else
969 | {
970 | Log(LogMsgType.Incoming, str);
971 | }
972 | }
973 | Thread.Sleep(100);
974 | }
975 | catch (Exception e)
976 | {
977 | Console.WriteLine(e.ToString());
978 | //MessageBox.Show(e.ToString());
979 | }
980 | }
981 | sbpStatus.Content = "状态:已断开";
982 | }
983 |
984 | private void Connect()
985 | {
986 | sw_igoahead = false;
987 | sw_ugoahead = true;
988 | sw_igoahead = false;
989 | sw_echo = true;
990 | sw_termsent = false;
991 |
992 | Console.WriteLine("连接服务器" + txtRemoteAddress.Text + "...");
993 |
994 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
995 | socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
996 |
997 | IPAddress ipAdd = IPAddress.Parse(txtRemoteAddress.Text);
998 | int port = System.Convert.ToInt32(txtPort.Text);
999 | IPEndPoint hostEndPoint = new IPEndPoint(ipAdd, port);
1000 |
1001 | try
1002 | {
1003 | socket.Connect(hostEndPoint);
1004 | }
1005 | catch (Exception e)
1006 | {
1007 | Console.WriteLine(e.ToString());
1008 | this.sbpStatus.Content = "状态:服务器未准备好";
1009 | return;
1010 | }
1011 |
1012 | if (socket.Connected)
1013 | {
1014 | //更新状态
1015 | sbpStatus.Content = "状态:已连接";
1016 | sbpHost.Text = "服务器地址:" + txtRemoteAddress.Text;
1017 |
1018 | Thread thread = new Thread(new ThreadStart(this.TelnetThread));
1019 | thread.Start();
1020 | //Control.CheckForIllegalCrossThreadCalls = false;
1021 | }
1022 | }
1023 |
1024 | private void Disconnect()
1025 | {
1026 | if (socket != null && socket.Connected)
1027 | {
1028 | socket.Shutdown(SocketShutdown.Both);
1029 | socket.Close();
1030 | }
1031 | sbpStatus.Content = "状态:断开连接...";
1032 |
1033 | }
1034 |
1035 | #endregion
1036 |
1037 | #region 属性
1038 | private DataMode CurrentDataMode
1039 | {
1040 | get
1041 | {
1042 | if (rbHex.IsEnabled)
1043 | {
1044 | return DataMode.Hex;
1045 | }
1046 | else
1047 | {
1048 | return DataMode.Text;
1049 | }
1050 | }
1051 | set
1052 | {
1053 | if (value == DataMode.Text)
1054 | {
1055 | rbText.IsChecked = true;
1056 | //MessageBox.Show(rbText.ToString());
1057 | }
1058 | else
1059 | {
1060 | rbHex.IsChecked = true;
1061 | }
1062 | }
1063 | }
1064 | #endregion
1065 |
1066 | #region 事件处理程序
1067 | //private void lnkAbout_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
1068 | //{
1069 | // // Show the user the about dialog
1070 | // (new frmAbout()).ShowDialog(this);
1071 | //}
1072 | //private void linkUserGuide_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
1073 | //{
1074 | // e.Link.Visited = true;
1075 | // Process.Start("http://www.educationtek.com/download/Telnet%20User%20Guide.htm");
1076 | //}
1077 | //private void pbLogo_Click(object sender, EventArgs e)
1078 | //{
1079 | // System.Diagnostics.Process.Start("http://www.educationtek.com/");
1080 | //}
1081 | //private void frmTelnet_Shown(object sender, EventArgs e)
1082 | //{
1083 | // this.Log(LogMsgType.Copyright, string.Format("{0} v{1} Started at {2}\n", Application.ProductName, Application.ProductVersion, DateTime.Now));
1084 | // this.Log(LogMsgType.Copyright, "Copyright \x00a9 2009-2010 www.educationtek.com All Right Reserved.\n");
1085 | //}
1086 | //private void frmTelnet_FormClosing(object sender, FormClosingEventArgs e)
1087 | //{
1088 | // // The form is closing, save the user's preferences
1089 | // SaveSettings();
1090 | //}
1091 |
1092 | private void rbText_CheckedChanged(object sender, EventArgs e)
1093 | {
1094 | if (rbText.IsChecked == true)
1095 | {
1096 | CurrentDataMode = DataMode.Text;
1097 | }
1098 | }
1099 | private void rbHex_CheckedChanged(object sender, EventArgs e)
1100 | {
1101 | if (rbHex.IsChecked == true)
1102 | {
1103 | CurrentDataMode = DataMode.Hex;
1104 | }
1105 | }
1106 |
1107 | private void btnOpenPort_Click(object sender, EventArgs e)
1108 | {
1109 | // If the port is open, close it.
1110 | if (socket.Connected)
1111 | {
1112 | Disconnect();
1113 | }
1114 | else
1115 | {
1116 | //rtbConsole.BeginInit();\
1117 |
1118 | // Open the port
1119 | Connect();
1120 | }
1121 |
1122 | // Change the state of the form's controls
1123 | EnableControls();
1124 |
1125 | // If the port is open, send focus to the send data box
1126 | if (socket.Connected)
1127 | {
1128 | txtSendData.Focus();
1129 | }
1130 | }
1131 |
1132 | private void btnSend_Click(object sender, RoutedEventArgs e)
1133 | {
1134 | SendData();
1135 |
1136 | }
1137 |
1138 | //private void txtSendData_KeyDown(object sender, KeyEventArgs e)
1139 | //{
1140 | // // If the user presses [ENTER], send the data now
1141 | // if (KeyHandled = e.KeyCode == Keys.Enter)
1142 | // {
1143 | // e.Handled = true;
1144 | // SendData();
1145 | // }
1146 | //}
1147 | //private void txtSendData_KeyPress(object sender, KeyPressEventArgs e)
1148 | //{
1149 | // e.Handled = KeyHandled;
1150 | //}
1151 |
1152 | //private void txtSendData_MouseDown(object sender, MouseButtonEventArgs e)
1153 | //{
1154 |
1155 | //}
1156 |
1157 | private void txtSendData_KeyDown_1(object sender, KeyEventArgs e)
1158 | {
1159 | // If the user presses [ENTER], send the data now
1160 | if (KeyHandled = e.Key == Key.Enter)
1161 | {
1162 | e.Handled = true;
1163 | SendData();
1164 | }
1165 | }
1166 |
1167 | private void txtSendData_KeyUp(object sender, KeyEventArgs e)
1168 | {
1169 | e.Handled = KeyHandled;
1170 |
1171 | }
1172 |
1173 | private void btnOpenPort_Click(object sender, RoutedEventArgs e)
1174 | {
1175 | // If the port is open, close it.
1176 | if (socket.Connected)
1177 | {
1178 | Disconnect();
1179 | }
1180 | else
1181 | {
1182 | //rtbConsole.BeginInit();\
1183 |
1184 |
1185 | // Open the port
1186 | Connect();
1187 | }
1188 |
1189 | // Change the state of the form's controls
1190 | EnableControls();
1191 |
1192 | // If the port is open, send focus to the send data box
1193 | if (socket.Connected)
1194 | {
1195 | txtSendData.Focus();
1196 | }
1197 | }
1198 | #endregion
1199 |
1200 |
1201 | private void textBoxReceive_SourceUpdated(object sender, DataTransferEventArgs e)
1202 | {
1203 |
1204 | }
1205 |
1206 | private void rbHex_Checked(object sender, RoutedEventArgs e)
1207 | {
1208 | if (rbHex.IsChecked == true)
1209 | {
1210 | CurrentDataMode = DataMode.Hex;
1211 | }
1212 | }
1213 |
1214 | private void rbText_Checked(object sender, RoutedEventArgs e)
1215 | {
1216 | if (rbText.IsChecked == true)
1217 | {
1218 | CurrentDataMode = DataMode.Text;
1219 | }
1220 | }
1221 |
1222 |
1223 |
1224 | ILogNet logNetSize = new LogNetFileSize(Application.ResourceAssembly + "\\LogBySize", 2 * 1024 * 1024);
1225 | ILogNet logNetTime = new LogNetDateTime(Application.ResourceAssembly + "\\LogByTime", GenerateMode.ByEveryDay);//按每天
1226 | private void TestButton_Click(object sender, RoutedEventArgs e)
1227 | {
1228 | // 一般日志写入
1229 | logNet.WriteDebug("调试信息");
1230 | logNet.WriteInfo("一般信息");
1231 | logNet.WriteWarn("警告信息");
1232 | logNet.WriteError("错误信息");
1233 | logNet.WriteFatal("致命信息");
1234 | logNet.WriteException(null, new IndexOutOfRangeException());
1235 |
1236 | // 带有关键字的写入,关键字建议为方法名或是类名,方便分析的时候归类搜索
1237 | logNet.WriteDebug("userButton1_Click", "调试信息");
1238 | logNet.WriteInfo("TestForm", "一般信息");
1239 | logNet.WriteWarn("随便什么", "警告信息");
1240 | logNet.WriteError("userButton1_Click", "错误信息");
1241 | logNet.WriteFatal("userButton1_Click", "致命信息");
1242 | logNet.WriteException("userButton1_Click", new IndexOutOfRangeException());
1243 |
1244 | // 日志查看器
1245 | using (HslCommunication.LogNet.FormLogNetView form = new HslCommunication.LogNet.FormLogNetView())
1246 | {
1247 | form.ShowDialog();
1248 | }
1249 | }
1250 |
1251 | }
1252 | }
1253 |
--------------------------------------------------------------------------------
/KeyencePLC/PLC.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Net.Sockets;
7 | using System.Windows;
8 | using HslCommunication;
9 | using HslCommunication.LogNet;
10 | using System.Threading;
11 | using System.Net;
12 |
13 | namespace KeyencePLC
14 | {
15 | public class PLC : IDisposable
16 | {
17 |
18 | #region 公共枚举
19 | public enum DataMode { Text, Hex }
20 | public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error, Copyright };
21 | #endregion
22 |
23 |
24 | #region PLC通信相关定义 Disposable注销
25 | private TcpClient _PLCTcpClient;
26 | private NetworkStream _PLCTcpStream;
27 | private string PLC_IP;
28 | private int PLC_Port;
29 |
30 |
31 | // The main control for communicating through the telnet port
32 | private Socket socket;
33 | private short[] parsedata = new short[10];
34 | protected bool sw_ugoahead;
35 | protected bool sw_igoahead;
36 | protected bool sw_echo;
37 | protected bool sw_termsent;
38 |
39 |
40 |
41 | private ILogNet logNet = new LogNetSingle(Application.ResourceAssembly + "\\Logs\\Log.txt");
42 |
43 | private DataMode CurrentDataMode
44 | {
45 | get
46 | {
47 | //if (rbHex.IsEnabled)
48 | //{
49 | // return DataMode.Hex;
50 | //}
51 | //else
52 | //{
53 | // return DataMode.Text;
54 | //}
55 | return DataMode.Hex;
56 | }
57 | set
58 | {
59 | //if (value == DataMode.Text)
60 | //{
61 | // rbText.IsChecked = true;
62 | // //MessageBox.Show(rbText.ToString());
63 | //}
64 | //else
65 | //{
66 | // rbHex.IsChecked = true;
67 | //}
68 | // return DataMode.Hex;
69 | }
70 | }
71 |
72 |
73 | // Various colors for logging info
74 | private System.Drawing.Color[] LogMsgTypeColor = { System.Drawing.Color.Blue, System.Drawing.Color.Green, System.Drawing.Color.Black, System.Drawing.Color.Orange, System.Drawing.Color.Red, System.Drawing.Color.OrangeRed };
75 |
76 | // Temp holder for whether a key was pressed
77 | private bool KeyHandled = false;
78 |
79 | private int checkPrint;
80 |
81 | //判断回收状态
82 | bool _disposed;
83 |
84 | public void Dispose()
85 | {
86 | Dispose(true);
87 | GC.SuppressFinalize(this);
88 | }
89 | ~PLC()
90 | {
91 | Dispose(false);
92 | }
93 | protected virtual void Dispose(bool disposing)
94 | {
95 | if (_disposed) return;
96 | if (disposing)
97 | {
98 |
99 | }
100 | _disposed = true;
101 | }
102 | public bool _isConnected
103 | {
104 | get
105 | {
106 | return _PLCTcpClient.Connected;
107 | }
108 | }
109 | #endregion
110 |
111 | #region PLC上位链路通信指令
112 |
113 |
114 |
115 |
116 | ///
117 | /// 功能 指令 相关页
118 | ///更改模式 Mn 13-10
119 | ///清除错误 ER 13-11
120 | ///错误编号确认? E 13-11
121 | ///查询机型? K 13-12
122 | ///动作模式确认? M 13-13
123 | ///时间设定 WRT 13-14
124 | ///强制置位/强制复位 ST/RS 13-15
125 | ///连续强制置位/连续强制复位 STS/RSS 13-16
126 | ///读取数据 RD 13-17
127 | ///读取连续数据 RDS 13-17
128 | ///读取连续数据 RDE 13-21
129 | ///写入数据 WR 13-22
130 | ///写入连续数据 WRS 13-22
131 | ///写入连续数据 WRE 13-23
132 | ///写入设定值 WS 13-24
133 | ///写入连续设定值 WSS 13-24
134 | ///监控器登录 MBS/MWS 13-24
135 | ///读取监控器 MBR/MWR 13-27
136 | ///注释读取 RDC 13-28
137 | ///库切换 BE 13-29
138 | ///读取扩展单元缓冲存储器 URD 13-30
139 | ///写入扩展单元缓冲存储器 UWR 13-31
140 | ///
141 | public enum QueryType
142 |
143 | {
144 | ///
145 | /// ProgramMode
146 | ///
147 | ProgramMode,
148 | ///
149 | /// RunMode
150 | ///
151 | Run,
152 | //ER清除
153 | ///
154 | /// //ER : 清除单元中发生的错误
155 | ///
156 | ER,
157 | ///
158 | /// //响应
159 | ///
160 | OK,
161 |
162 | ///
163 | /// //?E : 单元错误编号 //错误编号确认 ?E
164 | /// 编号错误内容编号错误内容编号错误内容
165 | ///010 子程序嵌套超限059 单元版本错误118 非法传输数据
166 | ///011 FOR-NEXT 嵌套超限063 需要重新接通电源120 看门狗定时器
167 | ///015 转换错误080 FLASH ROM 异常122 系统错误
168 | ///022 宏嵌套超限083 电池电压降低125 错误缓存溢出
169 | ///027 非法对象085 时钟数据消失127 自动加载失败
170 | ///029 梯形图堆栈错误086 RTC异常128 梯形图运算错误
171 | ///030 扫描时间超时087 存储卡异常129 单元错误
172 | ///031 梯形图堆栈溢出088 存储卡被拔出了131 FLASH ROM 格式
173 | ///040 无梯形图程序089 存储体访问中电源断开132 梯形图文件不正确
174 | ///050 单元设定检验和异常090 存储体访问完成等待134 自动加载文件夹
175 | ///051 单元设定信息未设定092 访问窗异常135 存储卡盖板打开
176 | ///052 单元未连接095 文件访问中136 存储卡被锁定
177 | ///053 扩展总线单元超时102 断电错误137 不支持的存储卡种类
178 | ///054 单元台数不一致103 电源中断处理超限141 CPU 存储器写入频率超限
179 | ///055 单元种类不一致106 复位异常142 CPU 存储器累积写入次数警告
180 | ///056 扩展总线通信错误107 系统错误143 CPU 存储器累积写入次数超限
181 | ///057 结束单元未连接
182 | ///
183 | EN,
184 |
185 | ///
186 | /// //?E : 用于查看 PLC 的型号。//?K 机型的问询
187 | ///
188 | PLC_K,
189 |
190 |
191 | ///
192 | /// 用于查看 CPU 单元当前的运行状态。
193 | ///
194 | MC,
195 |
196 | //错误编号
197 | ///
198 | /// 软元件编号异常 • 指定的软元件编号、存储体编号、单元 编号、地址超出了范围。
199 | ///
200 | E0,
201 | //• 指定了程序中没有使用的计时器、计数器、CTH、CTC 编号。• 没有执行监控器登录,但是执行了监控器读取。
202 | ///
203 | /// //E1 :命令异常 • 发送了不支持的指令。• 指定指令的方法不正确。
204 | ///
205 | E1,
206 | ///
207 | /// //E2 : 未登录程序 • CPU 单元中没有登录程序的状态下,发送了“M1(切换到 RUN 模式)”指令。
208 | ///
209 | E2,
210 | //CPU 单元的 RUN/PROG 开关在 PROG状态下,发送了“M1(切换到 RUN 模式)”指令
211 | ///
212 | ///
213 | ///
214 | E3,//E3 :
215 | ///
216 | /// //E4 : 禁止写入• 企图对禁止写入的程序更改计时器、计数器、的设定值
217 | ///
218 | E4,
219 | ///
220 | /// //E5 : 单元错误 在没有清除 CPU 单元错误的状态下,发送了 “M1(切换到 RUN 模式)”指令。 \
221 | ///
222 | E5,
223 | ///
224 | /// //E5 : 注释读取“RDC”指令选中的软元件中没有登录注释。PLC 的负荷较高,读取注释失败
225 | ///
226 | E6,
227 |
228 | ///
229 | /// //强制置位 ST_软元件种类+软元件编号 0D // 53 54 20 52 30 30 30 30 35 0D(强制置位 R00005)
230 | ///
231 |
232 | ST,
233 | //强制复位
234 | ///
235 | /// //强制复位
236 | ///
237 | RS,
238 |
239 | ///
240 | /// // 继电器 00000~199915
241 | ///
242 | R,
243 | ///
244 | /// //链路继电器 0000~7FFF
245 | ///
246 | B,
247 | ///
248 | /// //内部辅助继电器 00000~399915
249 | ///
250 | MR,
251 | ///
252 | /// //锁存继电器 00000~99915
253 | ///
254 | LR,
255 | ///
256 | /// //控制继电器 0000~7915
257 | ///
258 | CR,
259 | ///
260 | /// //定时器 0000~3999
261 | ///
262 | T,
263 | ///
264 | /// //计数器 C 0000~3999
265 | ///
266 | C,
267 | ///
268 | /// //工作继电器 VB 0000~F9FF
269 | ///
270 | VB,
271 |
272 |
273 |
274 | //可将软元件的数据格式(后缀)指定为.U/.S/.D/.L/.H/(不指定)。
275 | //.U : 16 位无符号十进制数
276 | //.S : 16 位有符号十进制数
277 | //.D : 32 位无符号十进制数
278 | //.L : 32 位有符号十进制数
279 | //.H : 16 位十六进制数
280 | //(不指定):因软元件类型而异
281 |
282 |
283 |
284 | //软元件种类 软元件编号*1 数据格式无指定 读取个数
285 | //软元件名称 KV-7500/7300 位/.U/.S/.H .D/.L
286 | //继电器*2 R(可省略) 00000~199915*3 (位) 0001~1000 0001~0500
287 | //链路继电器 B 0000~7FFF (位) 0001~1000 0001~0500
288 | //内部辅助继电器*2 MR 00000~399915 (位) 0001~1000 0001~0500
289 | //锁存继电器*2 LR 00000~99915 (位) 0001~1000 0001~0500
290 | //控制继电器 CR 0000~7915 (位) 0001~1000 0001~0500
291 | //工作继电器 VB 0000~F9FF (位) 0001~1000 0001~0500
292 | //数据存储器*2 DM 00000~65534 .U 0001~1000 0001~0500
293 | //扩展数据存储器*2 EM 00000~65534 .U 0001~1000 0001~0500
294 | //文件寄存器*2 FM 00000~32767 .U 0001~1000 0001~0500
295 | //ZF 00000~524287 .U 0001~1000 0001~0500
296 | //链路寄存器 W 0000~7FFF.U 0001~1000 0001~0500
297 | //临时数据存储器 TM 000~511 .U 001~512 001~256
298 | //变址寄存器 Z 01~12 .U 01~12 01~12
299 | //计时器 T 0000~3999 .D 001~120 001~120
300 | //计时器(当前值) TC 0000~3999 .D 001~120 001~120
301 | //计时器(设定值) TS 0000~3999 .D 001~120 001~120
302 | //计数器 C 0000~3999 .D 001~120 001~120
303 | //计数器(当前值) CC 0000~3999 .D 001~120 001~120
304 | //计数器(设定值) CS 0000~3999 .D 001~120 001~120
305 | //数字微调器 AT 0~7 .D 1~8 1~8
306 | //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
307 | //工作存储器 VM 00000~50999 .U 0001~1000 0001~0500
308 |
309 | ///
310 | /// //数据存储器 00000~65534 .U 0001~1000 0001~0500
311 | ///
312 | DM,
313 | ///
314 | /// //扩展数据存储器 00000~65534 .U 0001~1000 0001~0500
315 | ///
316 | EM,
317 | ///
318 | /// //文件寄存器 00000~32767 .U 0001~1000 0001~0500
319 | ///
320 | FM,
321 | ///
322 | /// // 文件寄存器 00000~524287 .U 0001~1000 0001~0500
323 | ///
324 | ZF,
325 | ///
326 | /// //链路寄存器 0000~7FFF .U 0001~1000 0001~0500
327 | ///
328 | W,
329 | ///
330 | /// //临时数据存储器 TM 000~511 .U 001~512 001~256
331 | ///
332 | TM,
333 | ///
334 | /// //变址寄存器 Z 01~12 .U 01~12 01~12
335 | ///
336 | Z,
337 | ///
338 | /// //计时器(当前值) TC 0000~3999 .D 001~120 001~120
339 | ///
340 | TC,
341 | ///
342 | /// //计时器(设定值) TS 0000~3999 .D 001~120 001~120
343 | ///
344 | TS,
345 | ///
346 | /// //计数器(当前值) CC 0000~3999 .D 001~120 001~120
347 | ///
348 | CC,
349 | ///
350 | /// //计数器(设定值) CS 0000~3999 .D 001~120 001~120
351 | ///
352 | CS,
353 | ///
354 | /// //数字微调器 AT 0~7 .D 1~8 1~8
355 | ///
356 | AT,
357 | ///
358 | /// //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
359 | ///
360 | CM,
361 | ///
362 | /// //工作存储器 VM 00000~50999 .U 0001~1000 0001~0500
363 | ///
364 | VM,
365 |
366 |
367 |
368 |
369 | _0, //0
370 | _1, //1
371 | _2, //2
372 | _3, //3
373 | _4, //4
374 | _5, //5
375 | _6, //6
376 | _7, //7
377 | _8,//8
378 | _9, //9
379 |
380 | //响应 OK 或者E错误
381 |
382 |
383 |
384 |
385 | //软元件种类 软元件编号*1
386 | //写入个数 软元件名称 KV-7500/7300
387 | //继电器*2 R(可省略) 00000~199915*3 01~16
388 | //链路继电器 B 0000~7FFF 01~16
389 | //内部辅助继电器*2 MR 00000~399915 01~16
390 | //锁存继电器*2 LR 00000~99915 01~16
391 | //控制继电器 CR 0000~7915 01~16
392 | //工作继电器 VB 0000~F9FF 01~16
393 |
394 | ///
395 | /// 连续强制置位/强制复位//<连续强制置位> STS 软元件种类+软元件编号 写入个数 0D // 53 54 53 20 52 30 30 30 30 35 20 30 31 30 0D(强制置位 R00005-R00015)
396 | ///
397 | STS,
398 |
399 | ///
400 | /// 连续强制复位 RSS 软元件种类+软元件编号 写入个数 0D 写入01-16
401 | ///
402 | RSS,
403 |
404 | //x响应OK E错误编号
405 |
406 |
407 |
408 | ///
409 | /// 读取数据 [RD]//RD: 读取一个指定软元件的数据。 RD 软元件种类+软元件编号+数据格式+0D //RD 52 44 20 52 30 30 30 31 30 0D 读取R00010的数据
410 | ///
411 | RD,
412 |
413 | ///
414 | /// /读取连续数据 [RDS]
415 | ///
416 | RDS, //?E : 单元错误编号
417 |
418 | ///
419 | /// /读取连续数据 同[RDS]
420 | ///
421 | RDE,
422 |
423 | ///
424 | /// .U :16 位无符号十进制数
425 | ///
426 | DOTU, //U
427 | ///
428 | /// .S :16 位有符号十进制数
429 | ///
430 | DOTS, //S
431 | ///
432 | /// .D :32 位无符号十进制数
433 | ///
434 | DOTD, //D
435 | ///
436 | /// .L :32 位有符号十进制数
437 | ///
438 | DOTL,//L
439 |
440 | ///
441 | ///
442 | /// .H :16 位十六进制值数
443 | ///
444 | DOTH, //H
445 |
446 |
447 | //响应
448 | // 数据1 数据2 ... 数据n 0D 0A
449 | //* n :发送指令时指定的读取个数
450 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
451 | //发送指令时指定的数据格式不同,值的范围也不同。
452 |
453 | //指定的数据格式 数据1~n
454 | //大小 范围
455 | //无指定 位 1字节 0 (OFF) 或1(ON)
456 | //.U 十进制数16位无符号 5字节 00000~65535
457 | //.S 十进制数16位有符号 6字节 -32768~+32767 (0は+00000)
458 | //.D 十进制数32位无符号 10字节 0000000000~4294967295
459 | //.L 十进制数32位有符号 11字节 -2147483648~+2147483647
460 | //(0为+0000000000)
461 | //.H 十六进制数16位 4字节 0000~FFFF
462 |
463 | //指定了.U/.S/.H 数据格式时,处理连续 16 位。
464 | //• 指定了.U/.S/.H 数据格式时,处理连续 16 位。
465 | //• 指定的继电器软元件不是通道的首软元件(R002、MR311 等)时,将跨到下一个通道处
466 | //理连续 16/32 位。
467 |
468 |
469 |
470 | //
471 | //* n: 发送指令时指定的读取个数
472 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
473 | //发送指令时指定的数据格式不同,值的范围也不同。
474 |
475 | //n: 发送指令时指定的读取个数
476 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
477 | //发送指令时指定的数据格式不同,值的范围也不同。
478 | // 指定的数据格式 数据1~n
479 | //大小 范围
480 | //.U(可省略) 十进制数16位无符号 5字节 00000~65535
481 | //.S 十进制数16位有符号 6字节 -32768~+32767 (0为+00000)
482 | //.D 十进制数32位无符号 10字节 0000000000~4294967295
483 | //.L 十进制数32位有符号 11字节 -2147483648~+2147483647
484 | //(0为+0000000000)
485 | //.H 十六进制数16位 4字节 0000~FFFF
486 |
487 | //• 对 Z 指定了.U/.S/.H 时,显示低位 16 位的值。
488 | //• 对 AT 指定了.U/.S/.H 时,显示低位 16 位的值。
489 | //错误响应同上
490 |
491 |
492 | // 将 R100~R103 以数据格式“位”读取时
493 | // RDS R100 4CR
494 | // 52H 44H 53H 20H 20H 52H 31H 30H 30H 34H0DH
495 | // 响应
496 |
497 | //R100:ON R101:OFF R102:ON R103:OFF
498 |
499 |
500 | //读取连续数据 [RDE 与RDS相同
501 |
502 |
503 |
504 |
505 | //软元件种类 软元件编号*1
506 | //数据格式
507 | //无指定
508 | //写入个数
509 | //软元件名称 KV-7500/7300 位
510 | ///.U/.S/.H.D/.L
511 | //继电器*2 R(可省略) 00000~199915*5 (位) 0001~1000 0001~0500
512 | //链路继电器 B 0000~7FFF (位) 0001~1000 0001~0500
513 | //内部辅助继电器*2 MR 00000~399915 (位) 0001~1000 0001~0500
514 | //锁存继电器*2 LR 00000~99915 (位) 0001~1000 0001~0500
515 | //控制继电器 CR 0000~7915 (位) 0001~1000 0001~0500
516 | //工作继电器 VB 0000~F9FF (位) 0001~1000 0001~0500
517 | //数据存储*2 DM 00000~65534 .U 0001~1000 0001~0500
518 | //扩展数据存储*2 EM 00000~65534 .U 0001~1000 0001~0500
519 | //文件寄存器*2 FM 00000~32767 .U 0001~1000 0001~0500
520 | // ZF 00000~524287 .U 0001~1000 0001~0500
521 | //链路寄存器 W 0000~7FFF.U 0001~1000 0001~0500
522 | //临时数据存储器 TM 000~511 .U 001~512 001~256
523 | //变址寄存器 Z 01~12 .U 01~12 01~12
524 | //定时器(当前值)*4 T*3, TC 0000~3999 .D 001~120 001~120
525 | //定时器(设定值)*4 TS 0000~3999 .D 001~120 001~120
526 | //计数器(当前值)*4 C*3, CC 0000~3999 .D 001~120 001~120
527 | //计数器(设定值)*4 CS 0000~3999 .D 001~120 001~120
528 | //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
529 | //工作存储器 VM 00000~63999 (位) 0001~1000 0001~0500
530 | // *1 软元件编号、写入个数可以清零。
531 | //*2 可对继电器、内部辅助继电器、锁存继电器、数据存储器、扩展数据存储器、文件寄存器进行 XYM 表示。 “
532 | //XYM 表示”,第 13-33 页
533 | //*3 指定定时器(T)、计数器(C)时,向当前值执行写入。
534 | //*4 指定.U/.S/.H的数据格式后,写入低位16位。
535 | //*5 KV-7000 系列的 CPU 功能版本为 2.2 以下时,继电器的范围为 00000~99915。
536 |
537 |
538 | ///
539 | /// 写入数据 [WR]/写入连续数据 [WRS]/// WR :将数据写入指定的软元件。/// WRS :连续写入指定个数的数据。
540 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
541 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
542 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
543 | ///.U :16 位无符号十进制数
544 | ///.S :16 位有符号十进制数
545 | ///.D :32 位无符号十进制数
546 | ///.L :32 位有符号十进制数
547 | ///.H :16 位十六进制值数
548 | ///(不指定) :因软元件类型而异
549 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
550 | ///数据格式的指定方法与 RD/RDS 指令相同。
551 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
552 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
553 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
554 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
555 | ///
556 | WR,//WR :将数据写入指定的软元件。 WR 软元件种类 软元件编号 数据格式 数据 0D
557 |
558 |
559 | ///
560 | /// //WRS :连续写入指定个数的数据。WRE写入连续数据与WRS相同 WRS 软元件种类 软元件编号 数据格式/// 写入设定值 [WS]/写入连续设定值 [WSS]WS/WSS 指令为以太网单元 KV-LE20A 兼容指令。其动作与 WR/WRS 相同。 写入个数 数据1 数据2 .... 数据n 0D
561 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
562 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
563 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
564 | ///.U :16 位无符号十进制数
565 | ///.S :16 位有符号十进制数
566 | ///.D :32 位无符号十进制数
567 | ///.L :32 位有符号十进制数
568 | ///.H :16 位十六进制值数
569 | ///(不指定) :因软元件类型而异
570 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
571 | ///数据格式的指定方法与 RD/RDS 指令相同。
572 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
573 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
574 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
575 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
576 | ///
577 | WRS,
578 |
579 | ///
580 | /// 连续写入指定个数的数据。WRE写入连续数据与WRS相同 WRS 软元件种类 软元件编号 数据格式/// 写入设定值 [WS]/写入连续设定值 [WSS]WS/WSS 指令为以太网单元 KV-LE20A 兼容指令。其动作与 WR/WRS 相同。 写入个数 数据1 数据2 .... 数据n 0D
581 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
582 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
583 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
584 | ///.U :16 位无符号十进制数
585 | ///.S :16 位有符号十进制数
586 | ///.D :32 位无符号十进制数
587 | ///.L :32 位有符号十进制数
588 | ///.H :16 位十六进制值数
589 | ///(不指定) :因软元件类型而异
590 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
591 | ///数据格式的指定方法与 RD/RDS 指令相同。
592 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
593 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
594 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
595 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
596 | ///
597 | WRE,
598 |
599 | // 指令和响应示例
600 | // 数据格式指定为“位”,写入 R100 ~R103 //WRS R100 4 1 0 1 0 ||57 52 53 20 52 31 30 30 20 34 20 31 20 30 20 31 20 30 0D
601 | // 数据格式指定为“.S”,写入 DM200 ~ DM202 || WRS DM200.S 3 +15025 - 05400 200 Cr || 57 52 53 20 44 4D 32 30 30 2E 53 20 33 20 2B 31 35 30 32 35 20 2D 30 35 34 30 30 20 32 30 30 0D
602 | // 响应 OK 4F 4B 0D 0A 写入数据可以消零。数据为正数时,可省略“+”。
603 | //但是“软元件类型”只能指定“T”、“C”、“CTC”。指定了“T”、“C”时,写入设定值
604 |
605 |
606 |
607 |
608 | //或字软元件登录表(MWS)。
609 | // 最多可登录 120 个数据。
610 | // MBS :对位软元件执行监控器登录。/// <位软元件监控器登录> || MBS 软元件种类 软元件编号 软元件种类 软元件编号 ... 软元件种类 软元件编号 || 4D 42 53 20 20 20 0D
611 |
612 | ///
613 | /// 监控器登录 MBS MWS将指定的软元件登录到位软元件登录表(MBS)
614 | ///
615 | MBS,
616 |
617 | //软元件种类软元件编号*1
618 | //软元件名称KV-7500/7300
619 | //继电器*2 R(可省略) 00000~199915*3
620 | //链路继电器B 0000~7FFF
621 | //内部辅助继电器*2 MR 00000~399915
622 | //锁存继电器*2 LR 00000~99915
623 | //控制继电器CR 0000~7915
624 | //定时器T 0000~3999
625 | //计数器C 0000~3999
626 | //工作继电器VB 0000~F9FF
627 | //
628 | ///
629 | /// MWS :对字软元件执行监控器登录。 // 字软元件监控器登录 MWS 软元件种类 软元件编号 数据格式 软元件种类 软元件编号 数据格式 ... Cr || 4D 57 53 20 20 20 0D
630 | ///
631 | MWS,
632 |
633 | //软元件种类软元件编号*1 数据格式
634 | //软元件名 KV-7500/7300 无指定
635 | //继电器*2*3 R(可省略) 00000~199915*4 .U
636 | //链路继电器*3 B 0000~7FFF.U
637 | //内部辅助继电器*2*3 MR 00000~399915 .U
638 | //锁存继电器*2*3 LR 00000~99915 .U
639 | //控制继电器*3 CR 0000~7915 .U
640 | //工作继电器VB 0000~F9FF.U
641 | //数据存储*2 DM 00000~65534 .U
642 | //扩展数据存储*2 EM 00000~65534 .U
643 | //文件寄存器*2 FM 00000~32767 .U
644 | //ZF 00000~524287 .U
645 | //链路寄存器W 0000~7FFF.U
646 | //临时数据存储器TM 000~511 .U
647 | //变址寄存器Z 01~12 .U
648 | //定时器(当前值) TC 0000~3999 .D
649 | //定时器(设定值) TS 0000~3999 .D
650 | //计数器(当前值) CC 0000~3999 .D
651 | //计数器(设定值) CS 0000~3999 .D
652 | //控制存储器CM 0000~5999 .U
653 | //工作存储器VM 0000~50999 .U
654 |
655 | //响应 OK 4F 4B || 异常 E
656 |
657 |
658 |
659 | ///
660 | /// 监控读取 [ MBR ]/[ MWR ]//指令 读取软元件登录表 M B R CR || 4DH 42H 52H 0DH
661 | /// 用于读取软元件登录表的软元件值。MBR :读取监控器登录后的位软元件值。 MWR :读取监控器登录后的字软元件值。
662 | ///
663 | MBR,
664 |
665 |
666 | ///
667 | /// 读取字软元件登录表 M W R CR || 4DH 57H 52H 0DH
668 | ///
669 | MWR,
670 |
671 |
672 | //响应 数据 20 数据 20 数据 20 数据 0D 0A
673 | //数据: 位软元件登录表或字软元件登录表中登录的软元件监控器结果。监控结果的格式与 RDS 指令的响应格式相同。
674 | //错误响应 E 1 CR LF || 45H 31H 0DH 0AH 命令异常
675 |
676 |
677 | //软元件种类软元件编号*1
678 | //软元件名称KV-7500/7300
679 | //继电器*2 R(可省略) 00000~199915*3
680 | //链路继电器B 0000~7FFF
681 | //内部辅助继电器*2 MR 00000~399915
682 | //锁存继电器*2 LR 00000~99915
683 | //控制继电器CR 0000~7915
684 | //数据存储*2 DM 00000~65534
685 | //扩展数据存储*2 EM 00000~65534
686 | //文件寄存器*2 FM 00000~32767
687 | //ZF 000000~524287
688 | //链路寄存器W 0000~7FFF
689 | //临时数据存储器TM 000~511
690 | //变址寄存器Z 01~12
691 | //定时器T 0000~3999
692 | //计数器C 0000~3999
693 | //控制存储CM 0000~5999
694 |
695 |
696 |
697 | ///
698 | /// 注释读取 [RDC] 用于读取指定软元件的注释。指令 RDC 用于读取指定软元件的注释 RDC 软元件种类R 软元件编号100 Cr || 52 44 43 20 52 31 30 30 0D
699 | /// 响应 数据CR LF 数据: 指令指定的软元件注释(32 字符)。注释在 32 字符以内时,添加空格(20H)。
700 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
701 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
702 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
703 | ///.U :16 位无符号十进制数
704 | ///.S :16 位有符号十进制数
705 | ///.D :32 位无符号十进制数
706 | ///.L :32 位有符号十进制数
707 | ///.H :16 位十六进制值数
708 | ///(不指定) :因软元件类型而异
709 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
710 | ///数据格式的指定方法与 RD/RDS 指令相同。
711 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
712 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
713 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
714 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
715 | /// 根据项目语言设定,输入转换后的字符串。在 RUN 模式下写入时,即使指定的软元件中登录了注释,也会显示异常时的响应 E6。
716 | ///
717 | RDC,
718 |
719 |
720 |
721 | ///
722 | /// 库切换 BE 切换文件寄存器的库。/// 响应 O K CR LF || 4FH 4BH 0DH 0AH ||OK :指令正常处理时,输入表示该状态的代码“OK”。
723 | /// // 库编号 :对于文件寄存器的库编号按照 0~15 的范围进行指定。 BE 库编号0 Cr || 42 45 20 30 0D
724 | ///
725 |
726 | BE,
727 |
728 | ///
729 | /// 读取扩展单元缓冲存储器 [URD] 用于从扩展单元缓冲存储器中连续读取指定个数的数据。
730 | /// URD 单元编号 地址 数据格式 读取个数 Cr || 55 52 44 20 30 31 20 30 30 30 31 30 31 30 30 0D || URD 01 0001 0100
731 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
732 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
733 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
734 | ///.U :16 位无符号十进制数
735 | ///.S :16 位有符号十进制数
736 | ///.D :32 位无符号十进制数
737 | ///.L :32 位有符号十进制数
738 | ///.H :16 位十六进制值数
739 | ///(不指定) :因软元件类型而异
740 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
741 | ///数据格式的指定方法与 RD/RDS 指令相同。
742 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
743 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
744 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
745 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
746 | ///
747 |
748 | URD, //URD 用于从扩展单元缓冲存储器中连续读取指定个数的数据。
749 |
750 |
751 | ///
752 | /// 写入扩展单元缓冲存储器 [UWR] 用于向扩展单元缓冲存储器连续写入指定个数的数据。\
753 | /// UWR 01 10000 .U 01 01 01 01 Cr || 55 57 52 20 30 31 20 31 30 30 30 30 2E 55 20 30 31 20 30 31 20 30 31 0D
754 | /// ///*1 单元编号 :在 00~48 的范围内指定单元编号。
755 | ///*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
756 | ///*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
757 | ///.U :16 位无符号十进制数
758 | ///.S :16 位有符号十进制数
759 | ///.D :32 位无符号十进制数
760 | ///.L :32 位有符号十进制数
761 | ///.H :16 位十六进制值数
762 | ///(不指定) :因软元件类型而异
763 | ///“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
764 | ///数据格式的指定方法与 RD/RDS 指令相同。
765 | ///“读取数据[RD]/读取连续数据[RDS]”,第13-17页
766 | ///*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
767 | ///数据格式指定为.D/.L 时,指定范围为 0001~0500。
768 | ///响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
769 | ///
770 |
771 | UWR, //用于向扩展单元缓冲存储器连续写入指定个数的数据。
772 |
773 |
774 | ///
775 | /// XYM表示法
776 | ///
777 | ///
778 | //软元件 名称可根据下表的 XYM 表示指定继电器(R)、内部辅助继电器(MR)、锁存继电器(LR)、数据存储器(DM)、扩展数据存储器(EM)、文件寄存器(FM)的软元件。
779 | //KEYENCE
780 | //表示XYM 表示
781 | //XYM 表示时的软元件编号
782 | //KV-7500/7300
783 | //继电器R
784 | //X 0000~1999F*
785 | //Y 0000~1999F*
786 | //内部辅助继电器MR M 00000~63999
787 | //锁存继电器LR L 0000~999F
788 | //数据存储器DM D 00000~65534
789 | //扩展数据存储器EM E 00000~65534
790 | //文件寄存器FM F 00000~32767
791 |
792 |
793 | }
794 | ///
795 | /// PLC 指令
796 | ///
797 | ///
798 |
799 | //Mn模式更改
800 | public const string ProgramMode = ("4D 30 0D");
801 | public const string Run = ("4D 31 0D");
802 | public const string OK = ("4F 4B 0D 0A");
803 | public const string E0 = ("45 30 0A"); ////软元件编号异常 • 指定的软元件编号、存储体编号、单元 编号、地址超出了范围。
804 | //• 指定了程序中没有使用的计时器、计数器、CTH、CTC 编号。• 没有执行监控器登录,但是执行了监控器读取。
805 | public const string E1 = ("45 31 0A"); //E1 :命令异常 • 发送了不支持的指令。• 指定指令的方法不正确。
806 | public const string E2 = ("45 32 0A"); //E2 : 未登录程序 • CPU 单元中没有登录程序的状态下,发送了“M1(切换到 RUN 模式)”指令。
807 | //CPU 单元的 RUN/PROG 开关在 PROG状态下,发送了“M1(切换到 RUN 模式)”指令
808 | public const string E3 = ("45 32 0A"); //E3 :
809 | public const string E4 = ("45 32 0A"); //E4 : 禁止写入• 企图对禁止写入的程序更改计时器、计数器、的设定值
810 | public const string E5 = ("45 35 0A"); //E5 : 单元错误 在没有清除 CPU 单元错误的状态下,发送了 “M1(切换到 RUN 模式)”指令。
811 | public const string E6 = ("45 36 0A"); //E5 : 注释读取“RDC”指令选中的软元件中没有登录注释。PLC 的负荷较高,读取注释失败
812 |
813 |
814 | //ER清除
815 | public const string ER = ("45 32 0A"); //ER : 清除单元中发生的错误
816 | //public const string OK = ("45 32 0A"); //响应
817 |
818 | //错误编号确认 ?E
819 | public const string EN = ("3F 45 0D"); //?E : 单元错误编号
820 |
821 |
822 | //?K 机型的问询
823 |
824 | public const string PLC_K = ("3F 4B 0D"); //?E : 用于查看 PLC 的型号。
825 |
826 | //响应
827 | public const string KV7300 = (" 35 34"); // KV-7300 : ‘54’( 35H、 34H)
828 | public const string KV7500 = (" 35 35"); // KV-7500 : ‘55’( 35H、 35H)
829 |
830 | public const string MC = ("3F 4D 0D"); //用于查看 CPU 单元当前的运行状态。
831 |
832 | //强制置位 [ST]/强制复位 [RS]
833 |
834 |
835 | //软元件种类 软元件编号*1
836 | //写入个数 软元件名称 KV-7500/7300
837 | //继电器*2 R(可省略) 00000~199915*3 01~16
838 | //链路继电器 B 0000~7FFF 01~16
839 | //内部辅助继电器*2 MR 00000~399915 01~16
840 | //锁存继电器*2 LR 00000~99915 01~16
841 | //控制继电器 CR 0000~7915 01~16
842 | //工作继电器 VB 0000~F9FF 01~16
843 |
844 | //强制置位
845 | public const string ST = ("53 54 20"); //强制置位 ST_软元件种类+软元件编号 0D // 53 54 20 52 30 30 30 30 35 0D(强制置位 R00005)
846 | //强制复位
847 | public const string RS = ("52 53 20"); //强制复位
848 |
849 | public const string R = ("52"); // 继电器 00000~199915
850 | public const string B = ("42"); //链路继电器 0000~7FFF
851 | public const string MR = ("4D 52"); //内部辅助继电器 00000~399915
852 | public const string LR = ("4C 52"); //锁存继电器 00000~99915
853 | public const string CR = ("43 52"); //控制继电器 0000~7915
854 | public const string T = ("54"); //定时器 0000~3999
855 | public const string C = ("43"); //计数器 C 0000~3999
856 | public const string VB = ("56 42"); //工作继电器 VB 0000~F9FF
857 |
858 |
859 |
860 | //可将软元件的数据格式(后缀)指定为.U/.S/.D/.L/.H/(不指定)。
861 | //.U : 16 位无符号十进制数
862 | //.S : 16 位有符号十进制数
863 | //.D : 32 位无符号十进制数
864 | //.L : 32 位有符号十进制数
865 | //.H : 16 位十六进制数
866 | //(不指定):因软元件类型而异
867 |
868 |
869 |
870 | //软元件种类 软元件编号*1 数据格式无指定 读取个数
871 | //软元件名称 KV-7500/7300 位/.U/.S/.H .D/.L
872 | //继电器*2 R(可省略) 00000~199915*3 (位) 0001~1000 0001~0500
873 | //链路继电器 B 0000~7FFF (位) 0001~1000 0001~0500
874 | //内部辅助继电器*2 MR 00000~399915 (位) 0001~1000 0001~0500
875 | //锁存继电器*2 LR 00000~99915 (位) 0001~1000 0001~0500
876 | //控制继电器 CR 0000~7915 (位) 0001~1000 0001~0500
877 | //工作继电器 VB 0000~F9FF (位) 0001~1000 0001~0500
878 | //数据存储器*2 DM 00000~65534 .U 0001~1000 0001~0500
879 | //扩展数据存储器*2 EM 00000~65534 .U 0001~1000 0001~0500
880 | //文件寄存器*2 FM 00000~32767 .U 0001~1000 0001~0500
881 | //ZF 00000~524287 .U 0001~1000 0001~0500
882 | //链路寄存器 W 0000~7FFF.U 0001~1000 0001~0500
883 | //临时数据存储器 TM 000~511 .U 001~512 001~256
884 | //变址寄存器 Z 01~12 .U 01~12 01~12
885 | //计时器 T 0000~3999 .D 001~120 001~120
886 | //计时器(当前值) TC 0000~3999 .D 001~120 001~120
887 | //计时器(设定值) TS 0000~3999 .D 001~120 001~120
888 | //计数器 C 0000~3999 .D 001~120 001~120
889 | //计数器(当前值) CC 0000~3999 .D 001~120 001~120
890 | //计数器(设定值) CS 0000~3999 .D 001~120 001~120
891 | //数字微调器 AT 0~7 .D 1~8 1~8
892 | //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
893 | //工作存储器 VM 00000~50999 .U 0001~1000 0001~0500
894 |
895 | public const string DM = ("44 4D"); //数据存储器 00000~65534 .U 0001~1000 0001~0500
896 | public const string EM = ("45 4D"); //扩展数据存储器 00000~65534 .U 0001~1000 0001~0500
897 | public const string FM = ("46 4D"); //文件寄存器 00000~32767 .U 0001~1000 0001~0500
898 | public const string ZF = ("3F 45 0D"); // 文件寄存器 00000~524287 .U 0001~1000 0001~0500
899 | public const string W = ("57"); //链路寄存器 0000~7FFF .U 0001~1000 0001~0500
900 | public const string TM = ("54 4D"); //临时数据存储器 TM 000~511 .U 001~512 001~256
901 | public const string Z = ("5A"); //变址寄存器 Z 01~12 .U 01~12 01~12
902 | public const string TC = ("54 43"); //计时器(当前值) TC 0000~3999 .D 001~120 001~120
903 | public const string TS = ("54 53"); //计时器(设定值) TS 0000~3999 .D 001~120 001~120
904 | public const string CC = ("43 43"); //计数器(当前值) CC 0000~3999 .D 001~120 001~120
905 | public const string CS = ("43 53 "); //计数器(设定值) CS 0000~3999 .D 001~120 001~120
906 | public const string AT = ("41 54"); //数字微调器 AT 0~7 .D 1~8 1~8
907 | public const string CM = ("43 4D"); //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
908 | public const string VM = ("5A"); //工作存储器 VM 00000~50999 .U 0001~1000 0001~0500
909 |
910 |
911 |
912 |
913 | public const string _0 = ("30"); //0
914 | public const string _1 = ("31"); //1
915 | public const string _2 = ("32"); //2
916 | public const string _3 = ("33"); //3
917 | public const string _4 = ("34"); //4
918 | public const string _5 = ("35"); //5
919 | public const string _6 = ("36"); //6
920 | public const string _7 = ("37"); //7
921 | public const string _8 = ("38"); //8
922 | public const string _9 = ("39"); //9
923 |
924 | //响应 OK 或者E错误
925 |
926 |
927 |
928 | ///
929 | /// 连续强制置位/强制复位
930 | ///
931 | ///
932 |
933 | //软元件种类 软元件编号*1
934 | //写入个数 软元件名称 KV-7500/7300
935 | //继电器*2 R(可省略) 00000~199915*3 01~16
936 | //链路继电器 B 0000~7FFF 01~16
937 | //内部辅助继电器*2 MR 00000~399915 01~16
938 | //锁存继电器*2 LR 00000~99915 01~16
939 | //控制继电器 CR 0000~7915 01~16
940 | //工作继电器 VB 0000~F9FF 01~16
941 |
942 | public const string STS = ("53 54 53 20"); //<连续强制置位> STS 软元件种类+软元件编号 写入个数 0D // 53 54 53 20 52 30 30 30 30 35 20 30 31 30 0D(强制置位 R00005-R00015)
943 | public const string RSS = ("52 53 53 20"); //<连续强制置位 RSS 软元件种类+软元件编号 写入个数 0D 写入01-16
944 |
945 | //x响应OK E错误编号
946 |
947 |
948 |
949 | ///
950 | /// 读取数据 [RD]/读取连续数据 [RDS]
951 | ///
952 |
953 |
954 | public const string RD = ("52 44 20"); //RD: 读取一个指定软元件的数据。 RD 软元件种类+软元件编号+数据格式+0D //RD 52 44 20 52 30 30 30 31 30 0D 读取R00010的数据
955 | public const string RDS = ("52 44 53 20"); //?E : 单元错误编号
956 |
957 |
958 | public const string DOTU = ("2E 55"); //U
959 | public const string DOTS = ("2E 53"); //S
960 | public const string DOTD = ("2E 44"); //D
961 | public const string DOTL = ("2E 4C"); //L
962 | public const string DOTH = ("2E 48"); //H
963 |
964 |
965 | //响应
966 | // 数据1 数据2 ... 数据n 0D 0A
967 | //* n :发送指令时指定的读取个数
968 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
969 | //发送指令时指定的数据格式不同,值的范围也不同。
970 |
971 | //指定的数据格式 数据1~n
972 | //大小 范围
973 | //无指定 位 1字节 0 (OFF) 或1(ON)
974 | //.U 十进制数16位无符号 5字节 00000~65535
975 | //.S 十进制数16位有符号 6字节 -32768~+32767 (0は+00000)
976 | //.D 十进制数32位无符号 10字节 0000000000~4294967295
977 | //.L 十进制数32位有符号 11字节 -2147483648~+2147483647
978 | //(0为+0000000000)
979 | //.H 十六进制数16位 4字节 0000~FFFF
980 |
981 | //指定了.U/.S/.H 数据格式时,处理连续 16 位。
982 | //• 指定了.U/.S/.H 数据格式时,处理连续 16 位。
983 | //• 指定的继电器软元件不是通道的首软元件(R002、MR311 等)时,将跨到下一个通道处
984 | //理连续 16/32 位。
985 |
986 |
987 |
988 | //
989 | //* n: 发送指令时指定的读取个数
990 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
991 | //发送指令时指定的数据格式不同,值的范围也不同。
992 |
993 | //n: 发送指令时指定的读取个数
994 | //数据1~n : 从指定的软元件编号开始,依次显示软元件中存储的值。
995 | //发送指令时指定的数据格式不同,值的范围也不同。
996 | // 指定的数据格式 数据1~n
997 | //大小 范围
998 | //.U(可省略) 十进制数16位无符号 5字节 00000~65535
999 | //.S 十进制数16位有符号 6字节 -32768~+32767 (0为+00000)
1000 | //.D 十进制数32位无符号 10字节 0000000000~4294967295
1001 | //.L 十进制数32位有符号 11字节 -2147483648~+2147483647
1002 | //(0为+0000000000)
1003 | //.H 十六进制数16位 4字节 0000~FFFF
1004 |
1005 | //• 对 Z 指定了.U/.S/.H 时,显示低位 16 位的值。
1006 | //• 对 AT 指定了.U/.S/.H 时,显示低位 16 位的值。
1007 | //错误响应同上
1008 |
1009 |
1010 | // 将 R100~R103 以数据格式“位”读取时
1011 | // RDS R100 4CR
1012 | // 52H 44H 53H 20H 20H 52H 31H 30H 30H 34H0DH
1013 | // 响应
1014 |
1015 | //R100:ON R101:OFF R102:ON R103:OFF
1016 |
1017 |
1018 | //读取连续数据 [RDE 与RDS相同
1019 |
1020 | ///
1021 | /// 写入数据 [WR]/写入连续数据 [WRS]
1022 | ///
1023 | /// WR :将数据写入指定的软元件。
1024 | /// WRS :连续写入指定个数的数据。
1025 |
1026 |
1027 | //软元件种类 软元件编号*1
1028 | //数据格式
1029 | //无指定
1030 | //写入个数
1031 | //软元件名称 KV-7500/7300 位
1032 | ///.U/.S/.H.D/.L
1033 | //继电器*2 R(可省略) 00000~199915*5 (位) 0001~1000 0001~0500
1034 | //链路继电器 B 0000~7FFF (位) 0001~1000 0001~0500
1035 | //内部辅助继电器*2 MR 00000~399915 (位) 0001~1000 0001~0500
1036 | //锁存继电器*2 LR 00000~99915 (位) 0001~1000 0001~0500
1037 | //控制继电器 CR 0000~7915 (位) 0001~1000 0001~0500
1038 | //工作继电器 VB 0000~F9FF (位) 0001~1000 0001~0500
1039 | //数据存储*2 DM 00000~65534 .U 0001~1000 0001~0500
1040 | //扩展数据存储*2 EM 00000~65534 .U 0001~1000 0001~0500
1041 | //文件寄存器*2 FM 00000~32767 .U 0001~1000 0001~0500
1042 | // ZF 00000~524287 .U 0001~1000 0001~0500
1043 | //链路寄存器 W 0000~7FFF.U 0001~1000 0001~0500
1044 | //临时数据存储器 TM 000~511 .U 001~512 001~256
1045 | //变址寄存器 Z 01~12 .U 01~12 01~12
1046 | //定时器(当前值)*4 T*3, TC 0000~3999 .D 001~120 001~120
1047 | //定时器(设定值)*4 TS 0000~3999 .D 001~120 001~120
1048 | //计数器(当前值)*4 C*3, CC 0000~3999 .D 001~120 001~120
1049 | //计数器(设定值)*4 CS 0000~3999 .D 001~120 001~120
1050 | //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
1051 | //工作存储器 VM 00000~63999 (位) 0001~1000 0001~0500
1052 | // *1 软元件编号、写入个数可以清零。
1053 | //*2 可对继电器、内部辅助继电器、锁存继电器、数据存储器、扩展数据存储器、文件寄存器进行 XYM 表示。 “
1054 | //XYM 表示”,第 13-33 页
1055 | //*3 指定定时器(T)、计数器(C)时,向当前值执行写入。
1056 | //*4 指定.U/.S/.H的数据格式后,写入低位16位。
1057 | //*5 KV-7000 系列的 CPU 功能版本为 2.2 以下时,继电器的范围为 00000~99915。
1058 |
1059 |
1060 |
1061 | public const string WR = ("57 52"); //WR :将数据写入指定的软元件。 WR 软元件种类 软元件编号 数据格式 数据 0D
1062 | public const string WRS = ("57 52 53"); //WRS :连续写入指定个数的数据。 WRS 软元件种类 软元件编号 数据格式 写入个数 数据1 数据2 .... 数据n 0D
1063 |
1064 | // 指令和响应示例
1065 | // 数据格式指定为“位”,写入 R100 ~R103 //WRS R100 4 1 0 1 0 ||57 52 53 20 52 31 30 30 20 34 20 31 20 30 20 31 20 30 0D
1066 | // 数据格式指定为“.S”,写入 DM200 ~ DM202 || WRS DM200.S 3 +15025 - 05400 200 Cr || 57 52 53 20 44 4D 32 30 30 2E 53 20 33 20 2B 31 35 30 32 35 20 2D 30 35 34 30 30 20 32 30 30 0D
1067 | // 响应 OK 4F 4B 0D 0A 写入数据可以消零。数据为正数时,可省略“+”。
1068 | ///
1069 | /// WRE写入连续数据与WRS相同
1070 | ///
1071 | /// 写入设定值 [WS]/写入连续设定值 [WSS]WS/WSS 指令为以太网单元 KV-LE20A 兼容指令。其动作与 WR/WRS 相同。
1072 | //但是“软元件类型”只能指定“T”、“C”、“CTC”。指定了“T”、“C”时,写入设定值
1073 |
1074 |
1075 |
1076 |
1077 | ///监控器登录 MBS MWS将指定的软元件登录到位软元件登录表(MBS)或字软元件登录表(MWS)。
1078 | /// 最多可登录 120 个数据。
1079 | /// MBS :对位软元件执行监控器登录。
1080 | /// MWS :对字软元件执行监控器登录。
1081 | /// <位软元件监控器登录> || MBS 软元件种类 软元件编号 软元件种类 软元件编号 ... 软元件种类 软元件编号 || 4D 42 53 20 20 20 0D
1082 |
1083 | public const string MBS = ("4D 42 53");
1084 |
1085 | //软元件种类软元件编号*1
1086 | //软元件名称KV-7500/7300
1087 | //继电器*2 R(可省略) 00000~199915*3
1088 | //链路继电器B 0000~7FFF
1089 | //内部辅助继电器*2 MR 00000~399915
1090 | //锁存继电器*2 LR 00000~99915
1091 | //控制继电器CR 0000~7915
1092 | //定时器T 0000~3999
1093 | //计数器C 0000~3999
1094 | //工作继电器VB 0000~F9FF
1095 | // 字软元件监控器登录 MWS 软元件种类 软元件编号 数据格式 软元件种类 软元件编号 数据格式 ... Cr || 4D 57 53 20 20 20 0D
1096 |
1097 | public const string MWS = ("4D 57 53");
1098 |
1099 | //软元件种类软元件编号*1 数据格式
1100 | //软元件名 KV-7500/7300 无指定
1101 | //继电器*2*3 R(可省略) 00000~199915*4 .U
1102 | //链路继电器*3 B 0000~7FFF.U
1103 | //内部辅助继电器*2*3 MR 00000~399915 .U
1104 | //锁存继电器*2*3 LR 00000~99915 .U
1105 | //控制继电器*3 CR 0000~7915 .U
1106 | //工作继电器VB 0000~F9FF.U
1107 | //数据存储*2 DM 00000~65534 .U
1108 | //扩展数据存储*2 EM 00000~65534 .U
1109 | //文件寄存器*2 FM 00000~32767 .U
1110 | //ZF 00000~524287 .U
1111 | //链路寄存器W 0000~7FFF.U
1112 | //临时数据存储器TM 000~511 .U
1113 | //变址寄存器Z 01~12 .U
1114 | //定时器(当前值) TC 0000~3999 .D
1115 | //定时器(设定值) TS 0000~3999 .D
1116 | //计数器(当前值) CC 0000~3999 .D
1117 | //计数器(设定值) CS 0000~3999 .D
1118 | //控制存储器CM 0000~5999 .U
1119 | //工作存储器VM 0000~50999 .U
1120 |
1121 | //响应 OK 4F 4B || 异常 E
1122 |
1123 |
1124 |
1125 | ///
1126 | /// 监控读取 [ MBR ]/[ MWR ]
1127 | ///
1128 | /// 用于读取软元件登录表的软元件值。MBR :读取监控器登录后的位软元件值。 MWR :读取监控器登录后的字软元件值。
1129 | ///
1130 |
1131 | public const string MBR = ("4D 42 52 0D"); //指令 读取软元件登录表 M B R CR || 4DH 42H 52H 0DH
1132 | public const string MWR = ("4D 57 52 0D"); // <读取字软元件登录表> M W R CR || 4DH 57H 52H 0DH
1133 |
1134 | //响应 数据 20 数据 20 数据 20 数据 0D 0A
1135 | //数据: 位软元件登录表或字软元件登录表中登录的软元件监控器结果。监控结果的格式与 RDS 指令的响应格式相同。
1136 | //错误响应 E 1 CR LF || 45H 31H 0DH 0AH 命令异常
1137 |
1138 | ///
1139 | /// 注释读取 [RDC] 用于读取指定软元件的注释。
1140 | ///
1141 | ///
1142 |
1143 | //软元件种类软元件编号*1
1144 | //软元件名称KV-7500/7300
1145 | //继电器*2 R(可省略) 00000~199915*3
1146 | //链路继电器B 0000~7FFF
1147 | //内部辅助继电器*2 MR 00000~399915
1148 | //锁存继电器*2 LR 00000~99915
1149 | //控制继电器CR 0000~7915
1150 | //数据存储*2 DM 00000~65534
1151 | //扩展数据存储*2 EM 00000~65534
1152 | //文件寄存器*2 FM 00000~32767
1153 | //ZF 000000~524287
1154 | //链路寄存器W 0000~7FFF
1155 | //临时数据存储器TM 000~511
1156 | //变址寄存器Z 01~12
1157 | //定时器T 0000~3999
1158 | //计数器C 0000~3999
1159 | //控制存储CM 0000~5999
1160 |
1161 |
1162 |
1163 | public const string RDC = ("52 44 43"); ////指令 RDC 用于读取指定软元件的注释 RDC 软元件种类R 软元件编号100 Cr || 52 44 43 20 52 31 30 30 0D
1164 | //响应 数据CR LF 数据: 指令指定的软元件注释(32 字符)。注释在 32 字符以内时,添加空格(20H)。
1165 | //根据项目语言设定,输入转换后的字符串。在 RUN 模式下写入时,即使指定的软元件中登录了注释,也会显示异常时的响应 E6。
1166 |
1167 |
1168 | ///
1169 | /// 库切换 BE 切换文件寄存器的库。
1170 | ///
1171 | /// 响应 O K CR LF || 4FH 4BH 0DH 0AH ||OK :指令正常处理时,输入表示该状态的代码“OK”。
1172 |
1173 |
1174 | public const string BE = ("42 45"); // 库编号 :对于文件寄存器的库编号按照 0~15 的范围进行指定。 BE 库编号0 Cr || 42 45 20 30 0D
1175 |
1176 | ///
1177 | /// 读取扩展单元缓冲存储器 [URD] 用于从扩展单元缓冲存储器中连续读取指定个数的数据。
1178 | ///
1179 | /// URD 单元编号 地址 数据格式 读取个数 Cr || 55 52 44 20 30 31 20 30 30 30 31 30 31 30 30 0D || URD 01 0001 0100
1180 | //*1 单元编号 :在 00~48 的范围内指定单元编号。
1181 | //*2 地址 :在0~59999的范围内指定扩展单元缓冲存储器的地址。
1182 | //*3 数据格式 :软元件的数据格式(后缀)可指定为.U/.S/.D/.L/.H/(不指定)。
1183 | //.U :16 位无符号十进制数
1184 | //.S :16 位有符号十进制数
1185 | //.D :32 位无符号十进制数
1186 | //.L :32 位有符号十进制数
1187 | //.H :16 位十六进制值数
1188 | //(不指定) :因软元件类型而异
1189 | //“ 数据格式指定为.D/.L 时的数据同时性”,第 13-33 页
1190 | //数据格式的指定方法与 RD/RDS 指令相同。
1191 | //“读取数据[RD]/读取连续数据[RDS]”,第13-17页
1192 | //*4 读取个数 :数据格式指定为.U/.S/.H 时,指定范围为 0001~1000。
1193 | //数据格式指定为.D/.L 时,指定范围为 0001~0500。
1194 | //响应 数据 数据 数据 数据 Cr Lf || 数据: 指定地址的扩展单元缓冲存储器中存储的数据。读取结果的格式与 RDS 指令的响应格式相同。
1195 |
1196 | public const string URD = ("55 52 44"); //URD 用于从扩展单元缓冲存储器中连续读取指定个数的数据。
1197 |
1198 |
1199 | ///
1200 | /// 写入扩展单元缓冲存储器 [UWR] 用于向扩展单元缓冲存储器连续写入指定个数的数据。
1201 | ///
1202 | /// UWR 01 10000 .U 01 01 01 01 Cr || 55 57 52 20 30 31 20 31 30 30 30 30 2E 55 20 30 31 20 30 31 20 30 31 0D
1203 | public const string UWR = ("55 57 52"); //用于向扩展单元缓冲存储器连续写入指定个数的数据。
1204 |
1205 |
1206 | ///
1207 | /// XYM表示法
1208 | ///
1209 | ///
1210 | //软元件 名称可根据下表的 XYM 表示指定继电器(R)、内部辅助继电器(MR)、锁存继电器(LR)、数据存储器(DM)、扩展数据存储器(EM)、文件寄存器(FM)的软元件。
1211 | //KEYENCE
1212 | //表示XYM 表示
1213 | //XYM 表示时的软元件编号
1214 | //KV-7500/7300
1215 | //继电器R
1216 | //X 0000~1999F*
1217 | //Y 0000~1999F*
1218 | //内部辅助继电器MR M 00000~63999
1219 | //锁存继电器LR L 0000~999F
1220 | //数据存储器DM D 00000~65534
1221 | //扩展数据存储器EM E 00000~65534
1222 | //文件寄存器FM F 00000~32767
1223 |
1224 |
1225 |
1226 |
1227 | #endregion
1228 |
1229 |
1230 | //#region PLC 指令和响应说明
1231 | //const string ProgramMode = ("4D 30 0D"); //Mn模式更改
1232 | // const string Run = ("4D 31 0D");
1233 | // const string OK = ("4F 4B 0D 0A");
1234 | // const string E0 = ("45 30 0A"); ////软元件编号异常 • 指定的软元件编号、存储体编号、单元 编号、地址超出了范围。
1235 | // const string E1 = ("45 31 0A"); //E1 :命令异常 • 发送了不支持的指令。• 指定指令的方法不正确。
1236 | // const string E2 = ("45 32 0A"); //E2 : 未登录程序 • CPU 单元中没有登录程序的状态下,发送了“M1(切换到 RUN 模式)”指令。
1237 | // const string E3 = ("45 32 0A"); //E3 :
1238 | // const string E4 = ("45 32 0A"); //E4 : 禁止写入• 企图对禁止写入的程序更改计时器、计数器、的设定值
1239 | // const string E5 = ("45 35 0A"); //E5 : 单元错误 在没有清除 CPU 单元错误的状态下,发送了 “M1(切换到 RUN 模式)”指令。
1240 | // const string E6 = ("45 36 0A"); //E5 : 注释读取“RDC”指令选中的软元件中没有登录注释。PLC 的负荷较高,读取注释失败
1241 | // const string ER = ("45 52 0D"); //ER : 清除单元中发生的错误
1242 | // const string EN = ("3F 45 0D "); //?E : 单元错误编号 //错误编号确认 ?E
1243 | // const string PLC_K = ("3F 4B 0D"); //?K : 用于查看 PLC 的型号。
1244 | // const string KV7300 = (" 35 34"); // KV-7300 : ‘54’( 35H、 34H)
1245 | // const string KV7500 = (" 35 35"); // KV-7500 : ‘55’( 35H、 35H)
1246 | // const string MC = ("3F 4D 0D"); //用于查看 CPU 单元当前的运行状态。
1247 | // const string ST = ("53 54 20"); //强制置位 ST_软元件种类+软元件编号 0D // 53 54 20 52 30 30 30 30 35 0D(强制置位 R00005)
1248 | // const string RS = ("52 53 20"); //强制复位
1249 | // const string R = ("52"); // 继电器 00000~199915
1250 | // const string B = ("42"); //链路继电器 0000~7FFF
1251 | // const string MR = ("4D 52"); //内部辅助继电器 00000~399915
1252 | // const string LR = ("4C 52"); //锁存继电器 00000~99915
1253 | // const string CR = ("43 52"); //控制继电器 0000~7915
1254 | // const string T = ("54"); //定时器 0000~3999
1255 | // const string C = ("43"); //计数器 C 0000~3999
1256 | // const string VB = ("56 42"); //工作继电器 VB 0000~F9FF
1257 | // const string DM = ("44 4D"); //数据存储器 00000~65534 .U 0001~1000 0001~0500
1258 | // const string EM = ("45 4D"); //扩展数据存储器 00000~65534 .U 0001~1000 0001~0500
1259 | // const string FM = ("46 4D"); //文件寄存器 00000~32767 .U 0001~1000 0001~0500
1260 | // const string ZF = ("3F 45 0D"); // 文件寄存器 00000~524287 .U 0001~1000 0001~0500
1261 | // const string W = ("57"); //链路寄存器 0000~7FFF .U 0001~1000 0001~0500
1262 | // const string TM = ("54 4D"); //临时数据存储器 TM 000~511 .U 001~512 001~256
1263 | // const string Z = ("5A"); //变址寄存器 Z 01~12 .U 01~12 01~12
1264 | // const string TC = ("54 43"); //计时器(当前值) TC 0000~3999 .D 001~120 001~120
1265 | // const string TS = ("54 53"); //计时器(设定值) TS 0000~3999 .D 001~120 001~120
1266 | // const string CC = ("43 43"); //计数器(当前值) CC 0000~3999 .D 001~120 001~120
1267 | // const string CS = ("43 53 "); //计数器(设定值) CS 0000~3999 .D 001~120 001~120
1268 | // const string AT = ("41 54"); //数字微调器 AT 0~7 .D 1~8 1~8
1269 | // const string CM = ("43 4D"); //控制存储器 CM 0000~5999 .U 0001~1000 0001~0500
1270 | // const string VM = ("5A"); //工作存储器 VM 00000~50999 .U 0001~1000 0001~0500
1271 | // const string _0 = ("30"); //0
1272 | // const string _1 = ("31"); //1
1273 | // const string _2 = ("32"); //2
1274 | // const string _3 = ("33"); //3
1275 | // const string _4 = ("34"); //4
1276 | // const string _5 = ("35"); //5
1277 | // const string _6 = ("36"); //6
1278 | // const string _7 = ("37"); //7
1279 | // const string _8 = ("38"); //8
1280 | // const string _9 = ("39"); //9
1281 | // const string STS = ("53 54 53 20"); //<连续强制置位> STS 软元件种类+软元件编号 写入个数 0D // 53 54 53 20 52 30 30 30 30 35 20 30 31 30 0D(强制置位 R00005-R00015)
1282 | // const string RSS = ("52 53 53 20"); //<连续强制置位 RSS 软元件种类+软元件编号 写入个数 0D 写入01-16
1283 | // const string RD = ("52 44 20"); //RD: 读取一个指定软元件的数据。 RD 软元件种类+软元件编号+数据格式+0D //RD 52 44 20 52 30 30 30 31 30 0D 读取R00010的数据
1284 | // const string RDS = ("52 44 53 20"); //RDS: 连续读取指定个数的软元件的数据。
1285 | // const string DOTU = ("2E 55 20"); //U
1286 | // const string DOTS = ("2E 53 20"); //S
1287 | // const string DOTD = ("2E 44 20"); //D
1288 | // const string DOTL = ("2E 4C 20"); //L
1289 | // const string DOTH = ("2E 48 20"); //H
1290 | // const string WR = ("57 52 20"); //WR :将数据写入指定的软元件。 WR 软元件种类 软元件编号 数据格式 数据 0D
1291 | // const string WRS = ("57 52 53 20"); //WRS :连续写入指定个数的数据。 WRS 软元件种类 软元件编号 数据格式 写入个数 数据1 数据2 .... 数据n 0D
1292 | // const string MBS = ("4D 42 53 20");
1293 | // const string MWS = ("4D 57 53 20");
1294 | // const string MBR = ("4D 42 52 0D 20"); //指令 读取软元件登录表 M B R CR || 4DH 42H 52H 0DH
1295 | // const string MWR = ("4D 57 52 0D 20"); // <读取字软元件登录表> M W R CR || 4DH 57H 52H 0DH
1296 | // const string RDC = ("52 44 43 20"); ////指令 RDC 用于读取指定软元件的注释 RDC 软元件种类R 软元件编号100 Cr || 52 44 43 20 52 31 30 30 0D
1297 | // const string BE = ("42 45 20"); // 库编号 :对于文件寄存器的库编号按照 0~15 的范围进行指定。 BE 库编号0 Cr || 42 45 20 30 0D
1298 | // const string URD = ("55 52 44 20"); //URD 用于从扩展单元缓冲存储器中连续读取指定个数的数据。
1299 | // const string UWR = ("55 57 52 20"); //用于向扩展单元缓冲存储器连续写入指定个数的数据。
1300 |
1301 | // #endregion
1302 |
1303 |
1304 | #region PLC读写函数
1305 | public PLC(string ip, int port)
1306 | {
1307 | _PLCTcpClient = new TcpClient();
1308 | PLC_Port = port;
1309 | PLC_IP = ip;
1310 | }
1311 |
1312 | ///
1313 | /// 向PLC读取连续数据 字符串数据
1314 | ///
1315 | /// 轮询的指令
1316 | /// 软元件类别
1317 | /// 起始位
1318 | /// 格式 .U .L .D .H
1319 | /// 读取的数量
1320 | ///
1321 | public static string QueryPLC(QueryType Qtype, string type, int startByte, string format, int numberOfBits)
1322 | {
1323 | string Str = "";
1324 | string Cr = "0D";
1325 | byte[] ReceiveBuff = new byte[128];
1326 | switch (Qtype)
1327 | {
1328 | case QueryType.ST:
1329 | Str = "ST " + type + startByte + Cr;
1330 | break;
1331 | case QueryType.RS:
1332 | Str = "RS " + type + startByte;
1333 | break;
1334 | case QueryType.STS:
1335 | Str = "STS " + type + startByte + " " + numberOfBits + Cr;
1336 | break;
1337 | case QueryType.RSS:
1338 | Str = "RSS " + type + startByte + " " + numberOfBits + Cr;
1339 | break;
1340 | case QueryType.RD:
1341 | Str = "RD " + type + startByte + format + Cr;
1342 | break;
1343 | case QueryType.RDS:
1344 | Str = "RDS " + type + startByte + format + " " + numberOfBits + Cr;
1345 | break;
1346 | case QueryType.RDE:
1347 | Str = "RDE " + type + startByte + format + " " + numberOfBits + Cr;
1348 | break;
1349 | case QueryType.URD: //读取扩展单元缓冲存储器
1350 | Str = "URD " + type + startByte + format + " " + numberOfBits;
1351 | break;
1352 | case QueryType.MBR: //读取位软元件
1353 | Str = "MBR ";
1354 | break;
1355 | case QueryType.MWR: //读取字软元件
1356 | Str = "MWR ";
1357 | break;
1358 | //case QueryType.WR:
1359 | // Str = "WR " + type + startByte + format + " " +
1360 | default:
1361 | break;
1362 |
1363 | }
1364 | return Str;
1365 |
1366 | }
1367 |
1368 | internal void QueryPLC(string v)
1369 | {
1370 | throw new NotImplementedException();
1371 | }
1372 |
1373 | ///
1374 | /// PLC数据单个字节写入 MBS软元件位登录 MWS 软元件字登录
1375 | ///
1376 | ///
1377 | ///
1378 | ///
1379 | ///
1380 | ///
1381 | ///
1382 | ///
1383 | public static string QueryPLC(QueryType Qtype, string type, int startByte, string format, int data, int numberOfBits)
1384 | {
1385 | string Str = "";
1386 | string Cr = "0D";
1387 | byte[] ReceiveBuff = new byte[128];
1388 | switch (Qtype)
1389 | {
1390 | case QueryType.WR:
1391 | Str = "WR " + type + startByte + format + " " + data;
1392 | break;
1393 | case QueryType.MBS:
1394 | Str = "MBS " + type + startByte + " ";
1395 | break;
1396 | case QueryType.RDC:
1397 | Str = "RDC " + type + startByte;
1398 | break;
1399 | case QueryType.BE:
1400 | Str = "BE " + type;
1401 | break;
1402 | default:
1403 | break;
1404 | }
1405 | return Str + Cr;
1406 | }
1407 |
1408 | ///
1409 | /// PLC中连续写入或读取软元件信息
1410 | ///
1411 | /// 读取指令
1412 | /// 软元件R MR LR
1413 | /// 起始地址
1414 | /// 格式 .U .L .H/param>
1415 | /// 要发送的数组/数据串
1416 | /// 发送位数
1417 | ///
1418 | public static string QueryPLC(QueryType Qtype, char type, int startByte, char format, int[] data, int numberOfBits)
1419 | {
1420 | string Str = "";
1421 | string Cr = "0D";
1422 | byte[] ReceiveBuff = new byte[128];
1423 | string QData = "";
1424 | foreach (int i in data)
1425 | {
1426 | string.Join(" ", type + QData, i);
1427 | }
1428 | switch (Qtype)
1429 | {
1430 | case QueryType.WRS: //不确定能否成功 需要每一次一个数据格式和软元件编号 数据格式+软元件编号
1431 | Str = "WRS " + type + startByte + format + " " + data;
1432 | break;
1433 | case QueryType.MBS: //不确定能否成功 需要每一次一个数据格式和软元件编号 数据格式+软元件编号
1434 | Str = "MBS " + type + startByte + " " + QData;
1435 | break;
1436 | case QueryType.RDC: //不确定能否成功 需要每一次一个数据格式和软元件编号 数据格式+软元件编号
1437 | Str = "MWS " + type + startByte + " " + QData;
1438 | break;
1439 | case QueryType.BE:
1440 | Str = "MBR " + type;
1441 | break;
1442 | default:
1443 | break;
1444 | case QueryType.UWR:
1445 | Str = "UWR " + numberOfBits + startByte + format + data;
1446 | break;
1447 | }
1448 | return Str + Cr;
1449 | }
1450 |
1451 |
1452 | public static string QueryPLC(QueryType Qtype, string type, int startByte)
1453 | {
1454 | string Str = "";
1455 | string Cr = "0D";
1456 | byte[] ReceiveBuff = new byte[128];
1457 | switch (Qtype)
1458 | {
1459 | case QueryType.ST:
1460 | Str = ST + type + startByte + Cr;
1461 | break;
1462 | case QueryType.RS:
1463 | Str = RS + type + startByte + Cr;
1464 | break;
1465 | case QueryType.MBR: //读取位软元件
1466 | Str = MBR + Cr;
1467 | break;
1468 | case QueryType.MWR: //读取字软元件
1469 | Str = MWR + Cr;
1470 | break;
1471 | default:
1472 | break;
1473 |
1474 | }
1475 | return Str;
1476 |
1477 | }
1478 |
1479 |
1480 | ///
1481 | /// 向PLC读取正常或错误指令
1482 | ///
1483 | ///
1484 | ///
1485 | public static string QueryPLC(QueryType QType)
1486 | {
1487 | string Str = "";
1488 | switch (QType)
1489 | {
1490 | case QueryType.E0:
1491 | Str = "内容:软元件编号异常+原因:1.指定的软元件编号、存储体编号、单元编号、地址超出了范围。2.指定了程序中没有使用的计时器、计数器、CTH、CTC 编号。3.没有执行监控器登录,但是执行了监控器读取。+处理办法:1.请指定规定范围内的编号。2.请确认程序,并指定程序使用的编号。3.请在监控器读取之前执行监控器登录。";
1492 | break;
1493 | case QueryType.E1:
1494 | Str = "内容:指令异常+原因:1.发送了不支持的指令。2.指定指令的方法不正确。+处理办法:1.请确认并发送正确的指令。";
1495 | break;
1496 | case QueryType.E2:
1497 | Str = "内容:程序未登录:1.CPU 单元中没有登录程序的状态下,发送了“M1(切换到 RUN 模式)”指令。2.CPU 单元的 RUN/PROG 开关在 PROG状态下,发送了“M1(切换到 RUN 模式)”指令。+处理办法:1.请在 CPU 单元中登录程序后发送指令。2.请将 CPU 单元的 RUN/PROG 开关切换到 RUN。";
1498 | break;
1499 | case QueryType.E4:
1500 | Str = "内容:禁止写入+原因:1.企图对禁止写入的程序更改计时器、计数器、的设定值。2.指定了程序中没有使用的计时器、计数器、CTH、CTC 编号。+处理办法:1请取消程序的禁止写入后,重新发送指令。";
1501 | break;
1502 | case QueryType.E5:
1503 | Str = "内容:单元错误+原因:1.在没有清除 CPU 单元错误的状态下,发送了 “M1(切换到 RUN 模式)”指令。+处理办法:1.请清除 CPU 单元的错误和错误原因后,重新发送指令。";
1504 | break;
1505 | case QueryType.E6:
1506 | Str = "内容:无注释+原因:1.注释读取“RDC”指令选中的软元件中没有登录注释。2.PLC 的负荷较高,读取注释失败。+处理办法:1.需要时,请登录软元件的注释。2.请在 PLC 负荷较低时执行,或重试。";
1507 | break;
1508 | case QueryType.OK:
1509 | Str = "OK :指令正常处理时,输入表示该状态的代码“OK”。";
1510 | break;
1511 |
1512 | }
1513 | return Str;
1514 | }
1515 |
1516 |
1517 |
1518 | ///
1519 | /// 向PLC读取或者写入单个Hex数值
1520 | ///
1521 | /// 指令类型
1522 | /// 软元件类型 R MR CR LR
1523 | /// 起始编号 100 200 300
1524 | /// 格式 .U .L .H
1525 | /// 写入或读取的位数
1526 | ///
1527 | public static string ReadHexString(QueryType Qtype, string type, string startByte, string format, string numberOfBits)
1528 | {
1529 | string Str = "";
1530 | string Cr = "0D";
1531 | byte[] BType = HexStringToBinary(type);
1532 | byte[] BStartByte = HexStringToBinary(startByte);
1533 | byte[] BFormat = HexStringToBinary(format);
1534 | byte[] BNumber = HexStringToBinary(numberOfBits);
1535 | byte[] ReceiveBuff = new byte[128];
1536 |
1537 |
1538 | switch (Qtype)
1539 | {
1540 | case QueryType.ST:
1541 | Str = ST + BType + BStartByte + Cr;
1542 | break;
1543 | case QueryType.RS:
1544 | Str = RS + BType + BStartByte + Cr;
1545 | break;
1546 | case QueryType.STS:
1547 | Str = STS + BType + BStartByte + " " + BNumber + Cr;
1548 | break;
1549 | case QueryType.RSS:
1550 | Str = RSS + BType + BStartByte + " " + BNumber + Cr;
1551 | break;
1552 | case QueryType.RD:
1553 | Str = RD + BType + BStartByte + BFormat + Cr;
1554 | break;
1555 | case QueryType.RDS:
1556 | Str = RDS + BType + BStartByte + BFormat + " " + BNumber + Cr;
1557 | break;
1558 | case QueryType.URD: //读取扩展单元缓冲存储器
1559 | Str = URD + BType + BStartByte + BFormat + " " + BNumber + Cr;
1560 | break;
1561 | case QueryType.MBR: //读取位软元件
1562 | Str = MBR;
1563 | break;
1564 | case QueryType.MWR: //读取字软元件
1565 | Str = MWR;
1566 | break;
1567 | //case QueryType.WR:
1568 | // Str = "WR " + type + startByte + format + " " +
1569 | default:
1570 | break;
1571 |
1572 | }
1573 | return Str;
1574 |
1575 | }
1576 |
1577 | ///
1578 | /// 向PLC发送单个指令
1579 | ///
1580 | ///
1581 | ///
1582 | public static string ReadHexString(QueryType Qtype)
1583 | {
1584 | string Str = "";
1585 | string Cr = "0D";
1586 | byte[] ReceiveBuff = new byte[128];
1587 |
1588 |
1589 | switch (Qtype)
1590 | {
1591 | case QueryType.ProgramMode://指定“0”时,CPU 单元切换到 PROGRAM 模式。
1592 | Str = ProgramMode;
1593 | break;
1594 | case QueryType.Run: //指定“1”时,CPU 单元切换到 RUN 模式。
1595 | Str = Run;
1596 | break;
1597 | case QueryType.OK: //OK :指令正常处理时,输入表示该状态的代码“OK”。
1598 | Str = "OK";
1599 | break;
1600 | case QueryType.ER: //用于清除 CPU 单元中发生的错误。ER 清除错误
1601 | Str = ER;
1602 | break;
1603 | case QueryType.EN: //用于检查 CPU 单元中发生的错误或异常。可在错误编号表中查看具体错误内容。 ?E 错误编号确认
1604 | Str = EN;
1605 | break;
1606 | case QueryType.PLC_K: //用于查看 PLC 的型号。
1607 | Str = PLC_K;
1608 | break;
1609 | case QueryType.MC: //用于查看 CPU 单元当前的运行状态。
1610 | Str = MC;
1611 | break;
1612 | case QueryType.MBR: //MBR :读取监控器登录后的位软元件值。
1613 | Str = MBR;
1614 | break;
1615 | case QueryType.MWR: //MWR :读取监控器登录后的字软元件值。
1616 | Str = MWR;
1617 | break;
1618 | //case QueryType.WR:
1619 | // Str = "WR " + type + startByte + format + " " +
1620 | default:
1621 | break;
1622 |
1623 | }
1624 | return Str;
1625 |
1626 | }
1627 |
1628 |
1629 |
1630 | public void PLCConnect()
1631 | {
1632 | try
1633 | {
1634 | _PLCTcpClient.Connect(PLC_IP, PLC_Port);
1635 | _PLCTcpStream = _PLCTcpClient.GetStream();
1636 | }
1637 | catch (Exception e)
1638 | {
1639 | MessageBox.Show(e.ToString());
1640 | }
1641 |
1642 | }
1643 |
1644 |
1645 |
1646 | public void PLCDisconnet()
1647 | {
1648 | if (_PLCTcpStream != null)
1649 | _PLCTcpStream.Close();
1650 | if (_PLCTcpClient != null)
1651 | _PLCTcpClient.Close();
1652 | }
1653 |
1654 |
1655 |
1656 | public void MonitorSendQuery(string query)
1657 | {
1658 | if (query != null)
1659 | {
1660 | byte[] SendBuff = HslCommunication.BasicFramework.SoftBasic.HexStringToBytes(query); //16进制转化为byte类型
1661 | _PLCTcpStream.Write(SendBuff, 0, SendBuff.Length);
1662 | }
1663 | }
1664 |
1665 |
1666 | public string MonitorReadQuery(int Locate)
1667 | {
1668 | string StringRead = "";
1669 | byte[] ReceiveBuff = new byte[Locate];
1670 | if (_PLCTcpStream.CanRead)
1671 | {
1672 | int ByteRead = _PLCTcpStream.Read(ReceiveBuff, 0, ReceiveBuff.Length);
1673 | string ResultRead = ByteArrayToHexString(ReceiveBuff);
1674 | //string Result = BitConverter.ToString(ReceiveBuff); //将数据转换为16进制
1675 | //string[] Str = Result.Trim().Split('-');
1676 | //string ResultNeed = Str[Locate];
1677 | //string D = Convert.ToString(Convert.ToInt32(ResultNeed, 16));
1678 | //StringRead = D;
1679 | StringRead = ResultRead;
1680 | return StringRead;
1681 | }
1682 | else
1683 | {
1684 | return null;
1685 | }
1686 | }
1687 |
1688 |
1689 | public string MonitorReadQuery()
1690 | {
1691 | string StringRead = "";
1692 | byte[] ReceiveBuff = new byte[64];
1693 | if (_PLCTcpStream.CanRead)
1694 | {
1695 | int ByteRead = _PLCTcpStream.Read(ReceiveBuff, 0, ReceiveBuff.Length);
1696 | string Result = BitConverter.ToString(ReceiveBuff); //将数据转换为16进制
1697 | string[] Str = Result.Trim().Split('-');
1698 | string ResultNeed = Str[0];
1699 | string D = Convert.ToString(Convert.ToInt32(ResultNeed, 16));
1700 | StringRead = D;
1701 | return StringRead;
1702 | }
1703 | else
1704 | {
1705 | return null;
1706 | }
1707 | }
1708 |
1709 | ///
1710 | /// 上位机读取DB数据
1711 | ///
1712 | ///
1713 | ///
1714 | public string MonitorReadDB(int Locate)
1715 | {
1716 | string StringRead = "";
1717 | byte[] ReceiveBuff = new byte[64];
1718 | if (_PLCTcpStream.CanRead)
1719 | {
1720 | int ByteRead = _PLCTcpStream.Read(ReceiveBuff, 0, ReceiveBuff.Length);
1721 | string Result = BitConverter.ToString(ReceiveBuff); //将数据转换为16进制
1722 | string[] Str = Result.Trim().Split('-');
1723 | string ResultNeedDB16 = Str[Locate];
1724 | string ResultNeedDB10 = Convert.ToString(Convert.ToInt32(ResultNeedDB16, 16)); //先转换为10进制
1725 | string ResultNeedDB2 = Convert.ToString(Convert.ToUInt32(ResultNeedDB10), 2); //在转换为2进制
1726 |
1727 | StringRead = ResultNeedDB2.PadLeft(8, '0');
1728 | return StringRead;
1729 | }
1730 | else
1731 | {
1732 | return null;
1733 | }
1734 |
1735 | }
1736 | #endregion
1737 |
1738 | #region Telnet Socket 通信指令
1739 | //向Telnet服务器发送命令
1740 | public void SocketSend(string msg)
1741 | {
1742 | System.Byte[] message = System.Text.Encoding.ASCII.GetBytes(msg.ToCharArray());
1743 | socket.Send(message, message.Length, 0);
1744 | }
1745 |
1746 | //向Telnet服务器发送命令
1747 | public void SocketSend(char[] chr)
1748 | {
1749 | System.Byte[] message = System.Text.Encoding.ASCII.GetBytes(chr);
1750 | socket.Send(message, message.Length, 0);
1751 | }
1752 |
1753 | //向Telnet服务器发送数据
1754 | public void SocketSend(byte[] data)
1755 | {
1756 | System.Byte[] message = data;
1757 | socket.Send(message, message.Length, 0);
1758 | }
1759 |
1760 | //接收数据
1761 | public string Receive()
1762 | {
1763 | //用于接收数据的缓冲
1764 | byte[] buf;
1765 | string result = "";
1766 |
1767 | int count = socket.Available;
1768 | if (count > 0)
1769 | {
1770 | buf = new byte[count];
1771 | socket.Receive(buf);
1772 | if (CurrentDataMode == DataMode.Hex)
1773 | {
1774 | result = ByteArrayToHexString(buf);
1775 | //MessageBox.Show(result);
1776 | //textBoxReceive.Text = result;
1777 | }
1778 | else
1779 | {
1780 | result = ProcessOptions(buf);
1781 | //MessageBox.Show(result);
1782 | //textBoxReceive.Text = result;
1783 | }
1784 | }
1785 |
1786 | return result;
1787 | }
1788 | #region
1789 | #if false
1790 | //处理命令字符,buf是包含数据的缓冲
1791 | private string ProcessOptions(byte[] buf)
1792 | {
1793 | string strNormal = "";
1794 | int i = 0;
1795 | while (i < buf.Length)
1796 | {
1797 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
1798 | i++;
1799 | }
1800 | return strNormal;
1801 | }
1802 | #else
1803 | #region 常量
1804 | const char GO_NORM = (char)0;
1805 | const char SUSP = (char)237;
1806 |
1807 | const char ABORT = (char)238;
1808 | const char SE = (char)240; //子选项结束Subnegotiation End
1809 | const char NOP = (char)241;
1810 | const char dm = (char)242; //Data Mark
1811 | const char BREAK = (char)243; //BREAK
1812 | const char IP = (char)244; //Interrupt Process
1813 | const char AO = (char)245; //Abort Output
1814 | const char AYT = (char)246; //Are you there
1815 | const char EC = (char)247; //Erase character
1816 | const char EL = (char)248; //Erase Line
1817 | const char GOAHEAD = (char)249; //Go Ahead
1818 | const char SB = (char)250; //子选项开始Subnegotiation Begin
1819 |
1820 | const char WILL = (char)251;
1821 | const char WONT = (char)252;
1822 | const char DO = (char)253;
1823 | const char DONT = (char)254;
1824 | const char IAC = (char)255;
1825 |
1826 | const char BINARY = (char)0;
1827 | const char IS = (char)0;
1828 | const char SEND = (char)1;
1829 | const char ECHO = (char)1;
1830 | const char RECONNECT = (char)2;
1831 | const char SGA = (char)3;
1832 | const char AMSN = (char)4;
1833 | const char STATUS = (char)5;
1834 | const char TIMING = (char)6;
1835 | const char RCTAN = (char)7;
1836 | const char OLW = (char)8;
1837 | const char OPS = (char)9;
1838 | const char OCRD = (char)10;
1839 | const char OHTS = (char)11;
1840 | const char OHTD = (char)12;
1841 | const char OFFD = (char)13;
1842 | const char OVTS = (char)14;
1843 | const char OVTD = (char)15;
1844 | const char OLFD = (char)16;
1845 | const char XASCII = (char)17;
1846 | const char LOGOUT = (char)18;
1847 | const char BYTEM = (char)19;
1848 | const char DET = (char)20;
1849 | const char SUPDUP = (char)21;
1850 | const char SUPDUPOUT = (char)22;
1851 | const char SENDLOC = (char)23;
1852 | const char TERMTYPE = (char)24;
1853 |
1854 | const char EOR = (char)25;
1855 | const char TACACSUID = (char)26;
1856 | const char OUTPUTMARK = (char)27;
1857 | const char TERMLOCNUM = (char)28;
1858 | const char REGIME3270 = (char)29;
1859 | const char X3PAD = (char)30;
1860 | const char NAWS = (char)31;
1861 | const char TERMSPEED = (char)32;
1862 | const char TFLOWCNTRL = (char)33;
1863 | const char LINEMODE = (char)34;
1864 | const char DISPLOC = (char)35;
1865 |
1866 | const char ENVIRON = (char)36;
1867 | const char AUTHENTICATION = (char)37;
1868 | const char UNKNOWN39 = (char)39;
1869 | const char EXTENDED_OPTIONS_LIST = (char)255;
1870 | const char RANDOM_LOSE = (char)256;
1871 |
1872 | const char cr = (char)13; //回车
1873 | const char LF = (char)10; //换行
1874 | const string BACK = "[P";
1875 | #endregion
1876 | //处理命令字符,buf是包含数据的缓冲
1877 | private string ProcessOptions(byte[] buf)
1878 | {
1879 | string strNormal = "";
1880 | int i = 0;
1881 | while (i < buf.Length)
1882 | {
1883 | if (buf[i] == IAC)
1884 | {
1885 | switch ((char)buf[++i])
1886 | {
1887 | case DO:
1888 | Console.Write("--------------接收到 DO ");
1889 | ProcessDo(buf[++i]);
1890 | break;
1891 | case DONT:
1892 | Console.Write("--------------接收到 DONT ");
1893 | ProcessDont(buf[++i]);
1894 | break;
1895 | case WONT:
1896 | Console.Write("--------------接收到 WONT ");
1897 | ProcessWont(buf[++i]);
1898 | break;
1899 | case WILL:
1900 | Console.Write("--------------接收到 WILL ");
1901 | ProcessWill(buf[++i]);
1902 | break;
1903 | case IAC:
1904 | //正常字符
1905 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
1906 | break;
1907 | case SB:
1908 | //子会话开始
1909 | int j = 0;
1910 | while (buf[++i] != SE)
1911 | {
1912 | parsedata[j++] = buf[i];
1913 | }
1914 | //子会话结束:
1915 | switch ((char)parsedata[0])
1916 | {
1917 | case TERMTYPE:
1918 | break;
1919 | case TERMSPEED:
1920 | if (parsedata[1] == 1)
1921 | {
1922 | Console.WriteLine("发送: SB TERMSPEED 57600,57600");
1923 | SocketSend(IAC + SB + TERMSPEED + IS + "57600,57600" + IAC + SE);
1924 | }
1925 | break;
1926 | }
1927 | break;
1928 | default:
1929 | Console.WriteLine("无效的命令" + buf[1]);
1930 | i++;
1931 | break;
1932 | };
1933 | }
1934 | else
1935 | {
1936 | //正常的文字
1937 | strNormal += System.Text.Encoding.Default.GetString(buf, i, 1);
1938 | }
1939 | i++;
1940 | }
1941 | return strNormal;
1942 | }
1943 |
1944 | private void ProcessDo(short ch)
1945 | {
1946 | //处理DO,以WILL或者WONT响应
1947 | switch ((char)ch)
1948 | {
1949 | case BINARY:
1950 | Console.WriteLine(BINARY);
1951 | SocketSend(new char[] { IAC, WONT, BINARY });
1952 | Console.WriteLine("发送: WONT BINARY");
1953 | break;
1954 | case ECHO:
1955 | Console.WriteLine(ECHO);
1956 | SocketSend(new char[] { IAC, WONT, ECHO });
1957 | Console.WriteLine("发送: WONT ECHO");
1958 | break;
1959 | case SGA:
1960 | Console.WriteLine(SGA);
1961 | if (!sw_igoahead)
1962 | {
1963 | SocketSend(new char[] { IAC, WILL, SGA });
1964 | Console.WriteLine("发送: WILL SGA");
1965 | sw_igoahead = true;
1966 | }
1967 | else
1968 | {
1969 | Console.WriteLine("不发送响应");
1970 | }
1971 | break;
1972 | case TERMSPEED:
1973 | Console.WriteLine(TERMSPEED);
1974 | SocketSend(new char[] { IAC, WILL, TERMSPEED });
1975 | Console.WriteLine("发送: WILL TERMSPEED");
1976 |
1977 | SocketSend(IAC + SB + TERMSPEED + (char)0 + "57600,57600" +
1978 | IAC + SE);
1979 | Console.WriteLine("发送:SB TERMSPEED 57600");
1980 | break;
1981 | case TFLOWCNTRL:
1982 | Console.WriteLine(TFLOWCNTRL);
1983 | SocketSend(new char[] { IAC, WONT, TFLOWCNTRL });
1984 | Console.WriteLine("发送: WONT TFLOWCNTRL");
1985 | break;
1986 | case LINEMODE:
1987 | Console.WriteLine(LINEMODE);
1988 | SocketSend(new char[] { IAC, WONT, LINEMODE });
1989 | Console.WriteLine("发送: WONT LINEMODE");
1990 | break;
1991 | case STATUS:
1992 | Console.WriteLine(STATUS);
1993 | SocketSend(new char[] { IAC, WONT, STATUS });
1994 | Console.WriteLine("发送: WONT STATUS");
1995 | break;
1996 | case TIMING:
1997 | Console.WriteLine(TIMING);
1998 | SocketSend(new char[] { IAC, WONT, TIMING });
1999 | Console.WriteLine("发送: WONT TIMING");
2000 | break;
2001 | case DISPLOC:
2002 | Console.WriteLine(DISPLOC);
2003 | SocketSend(new char[] { IAC, WONT, DISPLOC });
2004 | Console.WriteLine("发送: WONT DISPLOC");
2005 | break;
2006 | case ENVIRON:
2007 | Console.WriteLine(ENVIRON);
2008 | SocketSend(new char[] { IAC, WONT, ENVIRON });
2009 | Console.WriteLine("发送: WONT ENVIRON");
2010 | break;
2011 | case UNKNOWN39:
2012 | Console.WriteLine(UNKNOWN39);
2013 | SocketSend(new char[] { IAC, WILL, UNKNOWN39 });
2014 | Console.WriteLine("发送: WILL UNKNOWN39");
2015 | break;
2016 | case AUTHENTICATION:
2017 | Console.WriteLine(AUTHENTICATION);
2018 | SocketSend(new char[] { IAC, WONT, AUTHENTICATION });
2019 | Console.WriteLine("发送: WONT AUTHENTICATION");
2020 | Console.WriteLine("发送: SB AUTHENTICATION");
2021 | SocketSend(IAC + SB + AUTHENTICATION + (char)0 + (char)0 + (char)0 + (char)0 + "" + IAC + SE);
2022 | break;
2023 | default:
2024 | Console.WriteLine("未知的选项");
2025 | break;
2026 | }
2027 | }
2028 |
2029 | //处理DONT
2030 | private void ProcessDont(short ch)
2031 | {
2032 | switch ((char)ch)
2033 | {
2034 | case SE:
2035 | Console.WriteLine(SE);
2036 | Console.WriteLine("接收到: RECEIVED SE");
2037 | break;
2038 | case ECHO:
2039 | Console.WriteLine(ECHO);
2040 | if (!sw_echo)
2041 | {
2042 | sw_echo = true;
2043 | SocketSend(new char[] { IAC, WONT, ECHO });
2044 | Console.WriteLine("发送: WONT ECHO");
2045 | }
2046 | break;
2047 | case SGA:
2048 | Console.WriteLine(SGA);
2049 | if (!sw_ugoahead)
2050 | {
2051 | SocketSend(new char[] { IAC, WONT, SGA });
2052 | Console.WriteLine("发送: WONT SGA");
2053 | sw_ugoahead = true;
2054 | }
2055 | break;
2056 | case TERMSPEED:
2057 | Console.WriteLine(TERMSPEED);
2058 | SocketSend(new char[] { IAC, WONT, TERMSPEED });
2059 | Console.WriteLine("发送: WONT TERMSPEED");
2060 | break;
2061 | case TFLOWCNTRL:
2062 | Console.WriteLine(TFLOWCNTRL);
2063 | SocketSend(new char[] { IAC, WONT, TFLOWCNTRL });
2064 | Console.WriteLine("发送: WONT TFLOWCNTRL");
2065 | break;
2066 | case STATUS:
2067 | Console.WriteLine(STATUS);
2068 | SocketSend(new char[] { IAC, WONT, STATUS });
2069 | Console.WriteLine("发送: WONT STATUS");
2070 | break;
2071 | case TIMING:
2072 | Console.WriteLine(TIMING);
2073 | SocketSend(new char[] { IAC, WONT, TIMING });
2074 | Console.WriteLine("发送: WONT TIMING");
2075 | break;
2076 | case DISPLOC:
2077 | Console.WriteLine(DISPLOC);
2078 | SocketSend(new char[] { IAC, WONT, DISPLOC });
2079 | Console.WriteLine("发送: WONT DISPLOC");
2080 | break;
2081 | case ENVIRON:
2082 | Console.WriteLine(ENVIRON);
2083 | SocketSend(new char[] { IAC, WONT, ENVIRON });
2084 | Console.WriteLine("发送: WONT ENVIRON");
2085 | break;
2086 | case UNKNOWN39:
2087 | Console.WriteLine(UNKNOWN39);
2088 | SocketSend(new char[] { IAC, WILL, UNKNOWN39 });
2089 | Console.WriteLine("发送: WILL UNKNOWN39");
2090 | break;
2091 | default:
2092 | break;
2093 | }
2094 | }
2095 |
2096 | //处理WONT
2097 | private void ProcessWont(short ch)
2098 | {
2099 | switch ((char)ch)
2100 | {
2101 | case ECHO:
2102 | Console.WriteLine(ECHO);
2103 | if (sw_echo)
2104 | {
2105 | sw_echo = false;
2106 | SocketSend(new char[] { IAC, DONT, ECHO });
2107 | Console.WriteLine("发送: DONT ECHO");
2108 | }
2109 | break;
2110 | case SGA:
2111 | Console.WriteLine(SGA);
2112 | SocketSend(new char[] { IAC, DONT, SGA });
2113 | Console.WriteLine("发送: DONT SGA");
2114 | sw_igoahead = false;
2115 | break;
2116 | case TERMSPEED:
2117 | Console.WriteLine(TERMSPEED);
2118 | SocketSend(new char[] { IAC, DONT, TERMSPEED });
2119 | Console.WriteLine("发送: DONT TERMSPEED");
2120 | break;
2121 | case TFLOWCNTRL:
2122 | Console.WriteLine(TFLOWCNTRL);
2123 | SocketSend(new char[] { IAC, DONT, TFLOWCNTRL });
2124 | Console.WriteLine("发送: DONT TFLOWCNTRL");
2125 | break;
2126 | case LINEMODE:
2127 | Console.WriteLine(LINEMODE);
2128 | SocketSend(new char[] { IAC, DONT, LINEMODE });
2129 | Console.WriteLine("发送: DONT LINEMODE");
2130 | break;
2131 | case STATUS:
2132 | Console.WriteLine(STATUS);
2133 | SocketSend(new char[] { IAC, DONT, STATUS });
2134 | Console.WriteLine("发送: DONT STATUS");
2135 | break;
2136 | case TIMING:
2137 | Console.WriteLine(TIMING);
2138 | SocketSend(new char[] { IAC, WONT, TIMING });
2139 | Console.WriteLine("发送: WONT TIMING");
2140 | break;
2141 | case DISPLOC:
2142 | Console.WriteLine(DISPLOC);
2143 | SocketSend(new char[] { IAC, DONT, DISPLOC });
2144 | Console.WriteLine("发送: DONT DISPLOC");
2145 | break;
2146 | case ENVIRON:
2147 | Console.WriteLine(ENVIRON);
2148 | SocketSend(new char[] { IAC, DONT, ENVIRON });
2149 | Console.WriteLine("发送: DONT ENVIRON");
2150 | break;
2151 | case UNKNOWN39:
2152 | Console.WriteLine(UNKNOWN39);
2153 | SocketSend(new char[] { IAC, DONT, UNKNOWN39 });
2154 | Console.WriteLine("发送: DONT UNKNOWN39");
2155 | break;
2156 | default:
2157 | Console.WriteLine("未知的选项");
2158 | break;
2159 | }
2160 | }
2161 |
2162 | //处理WILL,以DO或者DONT响应
2163 | private void ProcessWill(short ch)
2164 | {
2165 | switch ((char)ch)
2166 | {
2167 | case ECHO:
2168 | Console.WriteLine(ECHO);
2169 | if (!sw_echo)
2170 | {
2171 | sw_echo = true;
2172 | SocketSend(new char[] { IAC, DO, ECHO });
2173 | Console.WriteLine("发送: DO ECHO");
2174 | }
2175 | break;
2176 | case SGA:
2177 | Console.WriteLine(SGA);
2178 | if (!sw_ugoahead)
2179 | {
2180 | SocketSend(new char[] { IAC, DO, SGA });
2181 | Console.WriteLine("发送: DO SGA");
2182 | sw_ugoahead = true;
2183 | }
2184 | else
2185 | {
2186 | Console.WriteLine("不发送响应");
2187 | }
2188 | break;
2189 | case TERMTYPE:
2190 | Console.WriteLine("TERMTYPE");
2191 | if (!sw_termsent)
2192 | {
2193 | SocketSend(new char[] { IAC, WILL, TERMTYPE });
2194 | SocketSend(IAC + SB + TERMTYPE + (char)0 + "VT100" + IAC + SE);
2195 | sw_termsent = true;
2196 | Console.WriteLine("发送: SB TERMTYPE VT100");
2197 | }
2198 | break;
2199 | case TERMSPEED:
2200 | Console.WriteLine(TERMSPEED);
2201 | SocketSend(new char[] { IAC, DONT, TERMSPEED });
2202 | Console.WriteLine("发送: DONT TERMSPEED");
2203 | break;
2204 | case TFLOWCNTRL:
2205 | Console.WriteLine(TFLOWCNTRL);
2206 | SocketSend(new char[] { IAC, DONT, TFLOWCNTRL });
2207 | Console.WriteLine("发送: DONT TFLOWCNTRL");
2208 | break;
2209 | case LINEMODE:
2210 | Console.WriteLine(LINEMODE);
2211 | SocketSend(new char[] { IAC, WONT, LINEMODE });
2212 | Console.WriteLine("发送: WONT LINEMODE");
2213 | break;
2214 | case STATUS:
2215 | Console.WriteLine(STATUS);
2216 | SocketSend(new char[] { IAC, DONT, STATUS });
2217 | Console.WriteLine("发送: DONT STATUS");
2218 | break;
2219 | case TIMING:
2220 | Console.WriteLine(TIMING);
2221 | SocketSend(new char[] { IAC, DONT, TIMING });
2222 | Console.WriteLine("发送: DONT TIMING");
2223 | break;
2224 | case DISPLOC:
2225 | Console.WriteLine(DISPLOC);
2226 | SocketSend(new char[] { IAC, DONT, DISPLOC });
2227 | Console.WriteLine("发送: DONT DISPLOC");
2228 | break;
2229 | case ENVIRON:
2230 | Console.WriteLine(ENVIRON);
2231 | SocketSend(new char[] { IAC, DONT, ENVIRON });
2232 | Console.WriteLine("发送: DONT ENVIRON");
2233 | break;
2234 | case UNKNOWN39:
2235 | Console.WriteLine(UNKNOWN39);
2236 | SocketSend(new char[] { IAC, DONT, UNKNOWN39 });
2237 | Console.WriteLine("发送: DONT UNKNOWN39");
2238 | break;
2239 | default:
2240 | Console.WriteLine("未知的选项");
2241 | break;
2242 | }
2243 | }
2244 | #endif
2245 | #endregion
2246 | public void TelnetThread()
2247 | {
2248 | while (socket.Connected)
2249 | {
2250 | try
2251 | {
2252 | string str = Receive();
2253 | str = str.Replace("\0", "");
2254 | string delim = "\b";
2255 | str = str.Trim(delim.ToCharArray());
2256 | if (str.Length > 0)
2257 | {
2258 | Console.WriteLine(str);
2259 | //Dispatcher.BeginInvoke(
2260 | // new Action(
2261 | // delegate
2262 | // {
2263 | // this.textBoxReceive.Text = str;
2264 | // Paragraph paragraphText = new Paragraph();
2265 | // paragraphText.Inlines.Add(str);
2266 | // this.rtbText.Document.Blocks.Add(paragraphText);
2267 | // }
2268 | // )
2269 | // );
2270 |
2271 | //MessageBox.Show(str);
2272 |
2273 | if (str == OUTPUTMARK + BACK)
2274 | {
2275 | ////BackupSpace键处理
2276 | //this.rtbConsole.IsReadOnly = false;
2277 | //int curpos = rtbConsole.SelectionStart;
2278 | //this.rtbConsole.Select(curpos - 1, 1);
2279 | //this.rtbConsole.SelectedText = "";
2280 | //this.rtbConsole.IsReadOnly = true;
2281 | }
2282 | else
2283 | {
2284 | //Log(LogMsgType.Incoming, str);
2285 | logNet.WriteDebug(str);
2286 | }
2287 | }
2288 | Thread.Sleep(100);
2289 |
2290 | }
2291 | catch (Exception e)
2292 | {
2293 | Console.WriteLine(e.ToString());
2294 | //MessageBox.Show(e.ToString());
2295 | }
2296 | }
2297 | //sbpStatus.Content = "状态:已断开";
2298 | }
2299 |
2300 |
2301 | public string TelnetThread(string str)
2302 | {
2303 |
2304 |
2305 |
2306 | while (socket.Connected)
2307 | {
2308 |
2309 | str = Receive();
2310 | str = str.Replace("\0", "");
2311 | string delim = "\b";
2312 | str = str.Trim(delim.ToCharArray());
2313 | Thread.Sleep(100);
2314 |
2315 | }
2316 |
2317 | return str;
2318 | }
2319 |
2320 | public void Connect()
2321 | {
2322 | sw_igoahead = false;
2323 | sw_ugoahead = true;
2324 | sw_igoahead = false;
2325 | sw_echo = true;
2326 | sw_termsent = false;
2327 |
2328 | //Console.WriteLine("连接服务器" + txtRemoteAddress.Text + "...");
2329 | logNet.WriteDebug("连接到服务器:" + PLC_K + " " + PLC_IP + PLC_Port);
2330 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2331 | socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
2332 |
2333 | //IPAddress ipAdd = IPAddress.Parse("192.168.1.105");
2334 | //int port = System.Convert.ToInt32("8501");
2335 |
2336 |
2337 | //IPAddress ipAdd = IPAddress.Parse("169.254.51.81");
2338 | //int port = System.Convert.ToInt32("8501");
2339 |
2340 |
2341 | IPAddress[] AddressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;
2342 | string LocalIP = AddressList[0].ToString();
2343 |
2344 |
2345 | IPAddress ipAdd = IPAddress.Parse(LocalIP);
2346 | //IPAddress ipAdd = IPAddress.Parse("192.158.125.119");
2347 |
2348 | int port = System.Convert.ToInt32("8501");
2349 |
2350 | IPEndPoint hostEndPoint = new IPEndPoint(ipAdd, port);
2351 |
2352 | try
2353 | {
2354 | socket.Connect(hostEndPoint);
2355 | }
2356 | catch (Exception e)
2357 | {
2358 | //Console.WriteLine(e.ToString());
2359 | logNet.WriteError(e.ToString());
2360 | //this.sbpStatus.Content = "状态:服务器未准备好";
2361 | return;
2362 | }
2363 |
2364 | if (socket.Connected)
2365 | {
2366 | //更新状态
2367 | //sbpStatus.Content = "状态:已连接";
2368 | //sbpHost.Text = "服务器地址:" + txtRemoteAddress.Text;
2369 |
2370 | Thread thread = new Thread(new ThreadStart(this.TelnetThread));
2371 | thread.Start();
2372 | //Control.CheckForIllegalCrossThreadCalls = false;
2373 | }
2374 | }
2375 |
2376 | public void Disconnect()
2377 | {
2378 | if (socket != null && socket.Connected)
2379 | {
2380 | socket.Shutdown(SocketShutdown.Both);
2381 | socket.Close();
2382 | }
2383 | //sbpStatus.Content = "状态:断开连接...";
2384 |
2385 | }
2386 |
2387 | #endregion
2388 |
2389 |
2390 | #region Telnet通信
2391 |
2392 | public void SendData(string str)
2393 | {
2394 | if (CurrentDataMode == DataMode.Text)
2395 | {
2396 | // Send the user's text straight out the port
2397 | SocketSend(str);
2398 |
2399 | // Show in the terminal window the user's text
2400 | //Log(LogMsgType.Outgoing, txtSendData.Text + "\n");
2401 | }
2402 | else
2403 | {
2404 | try
2405 | {
2406 | // Convert the user's string of hex digits (ex: B4 CA E2) to a byte array
2407 | byte[] data = HexStringToByteArray(str);
2408 |
2409 | // Send the binary data out the port
2410 | SocketSend(data);
2411 |
2412 | // Show the hex digits on in the terminal window
2413 | //Log(LogMsgType.Outgoing, ByteArrayToHexString(data) + "\n");
2414 | }
2415 | catch (FormatException)
2416 | {
2417 | // Inform the user if the hex string was not properly formatted
2418 | //Log(LogMsgType.Error, "Not properly formatted hex string: " + txtSendData.Text + "\n");
2419 | }
2420 | }
2421 | //txtSendData.SelectAll();
2422 | }
2423 |
2424 | #endregion
2425 |
2426 |
2427 | #region ASCII HEX Char 转换函数
2428 | /// Convert a string of hex digits (ex: E4 CA B2) to a byte array.
2429 | /// The string containing the hex digits (with or without spaces).
2430 | /// Returns an array of bytes.
2431 | public byte[] HexStringToByteArray(string s)
2432 | {
2433 | s = s.Replace(" ", "");
2434 | byte[] buffer = new byte[s.Length / 2];
2435 | for (int i = 0; i < s.Length; i += 2)
2436 | {
2437 | buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
2438 | }
2439 | return buffer;
2440 | }
2441 |
2442 | /// Converts an array of bytes into a formatted string of hex digits (ex: E4 CA B2)
2443 | /// The array of bytes to be translated into a string of hex digits.
2444 | /// Returns a well formatted string of hex digits with spacing.
2445 | public string ByteArrayToHexString(byte[] data)
2446 | {
2447 | StringBuilder sb = new StringBuilder(data.Length * 3);
2448 | foreach (byte b in data)
2449 | {
2450 | sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
2451 | }
2452 |
2453 | return sb.ToString().ToUpper();
2454 | }
2455 |
2456 | ///
2457 | /// 将一条十六进制字符串转换为ASCII
2458 | ///
2459 | /// 一条十六进制字符串
2460 | /// 返回一条ASCII码
2461 | public static string HexStringToASCII(string hexstring)
2462 | {
2463 | byte[] bt = HexStringToBinary(hexstring);
2464 | string lin = "";
2465 | for (int i = 0; i < bt.Length; i++)
2466 | {
2467 | lin = lin + bt[i] + " ";
2468 | }
2469 |
2470 |
2471 | string[] ss = lin.Trim().Split(new char[] { ' ' });
2472 | char[] c = new char[ss.Length];
2473 | int a;
2474 | for (int i = 0; i < c.Length; i++)
2475 | {
2476 | a = Convert.ToInt32(ss[i]);
2477 | c[i] = Convert.ToChar(a);
2478 | }
2479 |
2480 | string b = new string(c);
2481 | return b;
2482 | }
2483 |
2484 |
2485 | /**/
2486 | ///
2487 | /// 16进制字符串转换为二进制数组
2488 | ///
2489 | /// 用空格切割字符串
2490 | /// 返回一个二进制字符串
2491 | public static byte[] HexStringToBinary(string hexstring)
2492 | {
2493 |
2494 | string[] tmpary = hexstring.Trim().Split(' ');
2495 | byte[] buff = new byte[tmpary.Length];
2496 | for (int i = 0; i < buff.Length; i++)
2497 | {
2498 | buff[i] = Convert.ToByte(tmpary[i], 16);
2499 | }
2500 | return buff;
2501 | }
2502 |
2503 |
2504 | ///
2505 | /// 将byte型转换为字符串
2506 | ///
2507 | /// byte型数组
2508 | /// 目标字符串
2509 | private string ByteArrayToString(byte[] arrInput)
2510 | {
2511 | int i;
2512 | StringBuilder sOutput = new StringBuilder(arrInput.Length);
2513 | for (i = 0; i < arrInput.Length; i++)
2514 | {
2515 | sOutput.Append(arrInput[i].ToString("X2"));
2516 | }
2517 | //将此实例的值转换为System.String
2518 | return sOutput.ToString();
2519 | }
2520 |
2521 |
2522 |
2523 | ///
2524 | /// 对接收到的数据进行解包(将接收到的byte型数组解包为Unicode字符串)
2525 | ///
2526 | /// byte型数组
2527 | /// Unicode编码的字符串
2528 | public string disPackage(byte[] recbytes)
2529 | {
2530 | string temp = "";
2531 | foreach (byte b in recbytes)
2532 | temp += b.ToString("X2") + " ";//ToString("X2") 为C#中的字符串格式控制符
2533 | return temp;
2534 | }
2535 |
2536 | /**
2537 | * int转byte[]
2538 | * 该方法将一个int类型的数据转换为byte[]形式,因为int为32bit,而byte为8bit所以在进行类型转换时,知会获取低8位,
2539 | * 丢弃高24位。通过位移的方式,将32bit的数据转换成4个8bit的数据。注意 &0xff,在这当中,&0xff简单理解为一把剪刀,
2540 | * 将想要获取的8位数据截取出来。
2541 | * @param i 一个int数字
2542 | * @return byte[]
2543 | */
2544 | public static byte[] int2ByteArray(int i)
2545 | {
2546 | byte[] result = new byte[4];
2547 | result[0] = (byte)((i >> 24) & 0xFF);
2548 | result[1] = (byte)((i >> 16) & 0xFF);
2549 | result[2] = (byte)((i >> 8) & 0xFF);
2550 | result[3] = (byte)(i & 0xFF);
2551 | return result;
2552 | }
2553 | /**
2554 | * byte[]转int
2555 | * 利用int2ByteArray方法,将一个int转为byte[],但在解析时,需要将数据还原。同样使用移位的方式,将适当的位数进行还原,
2556 | * 0xFF为16进制的数据,所以在其后每加上一位,就相当于二进制加上4位。同时,使用|=号拼接数据,将其还原成最终的int数据
2557 | * @param bytes byte类型数组
2558 | * @return int数字
2559 | */
2560 | public static int bytes2Int(byte[] bytes)
2561 | {
2562 | int num = bytes[3] & 0xFF;
2563 | num |= ((bytes[2] << 8) & 0xFF00);
2564 | num |= ((bytes[1] << 16) & 0xFF0000);
2565 | num |= ((bytes[0] << 24) & 0xFF0000);
2566 | return num;
2567 | }
2568 |
2569 | public static string Int2String(int str)
2570 | {
2571 | string S = Convert.ToString(str);
2572 | return S;
2573 | }
2574 |
2575 | public static int String2Int(string str)
2576 | {
2577 | int a;
2578 | int.TryParse(str, out a);
2579 | int a1 = Convert.ToInt32(str);
2580 | return a1;
2581 | }
2582 |
2583 |
2584 | /*将int转为低字节在后,高字节在前的byte数组
2585 | b[0] = 11111111(0xff) & 01100001
2586 | b[1] = 11111111(0xff) & 00000000
2587 | b[2] = 11111111(0xff) & 00000000
2588 | b[3] = 11111111(0xff) & 00000000
2589 | */
2590 | public byte[] IntToByteArray2(int value)
2591 | {
2592 | byte[] src = new byte[4];
2593 | src[0] = (byte)((value >> 24) & 0xFF);
2594 | src[1] = (byte)((value >> 16) & 0xFF);
2595 | src[2] = (byte)((value >> 8) & 0xFF);
2596 | src[3] = (byte)(value & 0xFF);
2597 | return src;
2598 | }
2599 | //将高字节在前转为int,低字节在后的byte数组(与IntToByteArray2想对应)
2600 | public int ByteArrayToInt2(byte[] bArr)
2601 | {
2602 | if (bArr.Length != 4)
2603 | {
2604 | return -1;
2605 | }
2606 | return (int)((((bArr[0] & 0xff) << 24)
2607 | | ((bArr[1] & 0xff) << 16)
2608 | | ((bArr[2] & 0xff) << 8)
2609 | | ((bArr[3] & 0xff) << 0)));
2610 | }
2611 |
2612 | public static string StringToHexArray(string input)
2613 | {
2614 | char[] values = input.ToCharArray();
2615 | StringBuilder sb = new StringBuilder(input.Length * 3);
2616 | foreach (char letter in values)
2617 | {
2618 | // Get the integral value of the character.
2619 | int value = Convert.ToInt32(letter);
2620 | // Convert the decimal value to a hexadecimal value in string form.
2621 | string hexOutput = String.Format("{0:X}", value);
2622 | sb.Append(Convert.ToString(value, 16).PadLeft(2, '0').PadRight(3, ' '));
2623 | }
2624 |
2625 | return sb.ToString().ToUpper();
2626 |
2627 | #endregion
2628 |
2629 | }
2630 | }
2631 | }
2632 |
--------------------------------------------------------------------------------
/KeyencePLC/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("KeyencePLC")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("KeyencePLC")]
15 | [assembly: AssemblyCopyright("Copyright © 2018")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/KeyencePLC/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace KeyencePLC.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KeyencePLC.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/KeyencePLC/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/KeyencePLC/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | using static KeyencePLC.PLC;
12 |
13 | namespace KeyencePLC.Properties
14 | {
15 |
16 |
17 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
18 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
19 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
20 | {
21 |
22 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
23 |
24 | public static Settings Default
25 | {
26 | get
27 | {
28 | return defaultInstance;
29 | }
30 | }
31 |
32 | [global::System.Configuration.UserScopedSettingAttribute()]
33 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
34 | [global::System.Configuration.DefaultSettingValueAttribute("192.168.1.10")]
35 | public string HostIP
36 | {
37 | get
38 | {
39 | return ((string)(this["HostIP"]));
40 | }
41 | set
42 | {
43 | this["HostIP"] = value;
44 | }
45 | }
46 | [global::System.Configuration.UserScopedSettingAttribute()]
47 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
48 | [global::System.Configuration.DefaultSettingValueAttribute("8501")]
49 | public string Port
50 | {
51 | get
52 | {
53 | return ((string)(this["Port"]));
54 | }
55 | set
56 | {
57 | this["Port"] = value;
58 | }
59 | }
60 | [global::System.Configuration.UserScopedSettingAttribute()]
61 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
62 | [global::System.Configuration.DefaultSettingValueAttribute("Hex")]
63 | public DataMode DataMode
64 | {
65 | get
66 | {
67 | return ((global::KeyencePLC.PLC.DataMode)(this["DataMode"]));
68 | }
69 | set
70 | {
71 | this["DataMode"] = value;
72 | }
73 | }
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/KeyencePLC/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/KeyencePLC/WebPage/Demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/KeyencePLC/WebPage/WebAdaptor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Permissions;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace KeyencePLC.WebPage
9 | {
10 | class WebAdaptor
11 | {
12 | [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
13 | [System.Runtime.InteropServices.ComVisible(true)]//给予权限并设置可见
14 |
15 | public class WebAdaptec
16 | {
17 |
18 | public void ShowMsg(string Msg)
19 | {
20 | Console.WriteLine(Msg);
21 | }
22 |
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/KeyencePLC/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/KeyencePLC/readme.txt:
--------------------------------------------------------------------------------
1 | /**********************************************/
2 | /** keyence-plc 通讯相关程序库 **/
3 | /** 主要参考hslcommunicatuion通讯库 **/
4 | /** 通信包括socket 和telenet通信 **/
5 | /** 代码部分为个人编写,部分来源于互联网 **/
6 | /**********************************************/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # KeyencePLC
2 | a plc remote monitor for keyence,it contains the socket communication and telnet communciation
3 |
4 | it contains the third lib such as hslcommunication ,a lib for plc communication ; materialdesign a lib for metrowindow;mahapp a lib for metrowindow;
5 |
6 | a primary tool for debug
7 |
8 | with sendquery and readquery,you can read from and send to plc .
9 |
10 | 可用于PLC与上位机之间通信程序,程序基于.net平台开发
11 | 支持TCP/IP 和 串口通信
12 | 页面采用WPF设计
13 |
14 | ## 希望可以改进更多
15 |
--------------------------------------------------------------------------------