Browse Source

添加新Snap7协议工程文件,整理清除完成标志函数,添加延迟500ms,待测

yc_t 6 years ago
parent
commit
a4357d2812
61 changed files with 10161 additions and 538 deletions
  1. 20 2
      PLCLinker/CentralController.sln
  2. 1 1
      PLCLinker/centralController/FormNumberMachinePreview.Designer.cs
  3. 1 1
      PLCLinker/centralController/FormPLCConf.Designer.cs
  4. 413 413
      PLCLinker/centralController/FormRecordsManager.Designer.cs
  5. 18 18
      PLCLinker/centralController/FormRecordsManager.resx
  6. 69 69
      PLCLinker/centralController/FormSysConfig.Designer.cs
  7. 30 31
      PLCLinker/centralController/Terminal/Terminal.cs
  8. 4 0
      PLCLinker/centralController/centralController.csproj
  9. BIN
      PLCLinker/centralController/icon.ico
  10. BIN
      PLCLinker/centralController/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache
  11. BIN
      PLCLinker/centralController/obj/Release/centralController.Properties.Resources.resources
  12. 1 1
      PLCLinker/centralController/obj/Release/centralController.csproj.CoreCompileInputs.cache
  13. BIN
      PLCLinker/centralController/obj/Release/centralController.csproj.GenerateResource.Cache
  14. 2 2
      PLCLinker/centralController/serversettings.json
  15. 451 0
      PLCLinker/newPLCConnector/Form1.Designer.cs
  16. 554 0
      PLCLinker/newPLCConnector/Form1.cs
  17. 120 0
      PLCLinker/newPLCConnector/Form1.resx
  18. 194 0
      PLCLinker/newPLCConnector/LOG/LogManager.cs
  19. 25 0
      PLCLinker/newPLCConnector/LOG/LogTest.cs
  20. 87 0
      PLCLinker/newPLCConnector/LOG/log.cs
  21. BIN
      PLCLinker/newPLCConnector/PLC/PLCS7.dll
  22. 439 0
      PLCLinker/newPLCConnector/PLC/PLCS7.xml
  23. BIN
      PLCLinker/newPLCConnector/PLC/snap7Enc.dll
  24. 22 0
      PLCLinker/newPLCConnector/Program.cs
  25. 36 0
      PLCLinker/newPLCConnector/Properties/AssemblyInfo.cs
  26. 63 0
      PLCLinker/newPLCConnector/Properties/Resources.Designer.cs
  27. 117 0
      PLCLinker/newPLCConnector/Properties/Resources.resx
  28. 26 0
      PLCLinker/newPLCConnector/Properties/Settings.Designer.cs
  29. 7 0
      PLCLinker/newPLCConnector/Properties/Settings.settings
  30. 98 0
      PLCLinker/newPLCConnector/newPLCConnector.csproj
  31. 596 0
      PLCLinker/newPLCS7/PLCS7.cs
  32. 36 0
      PLCLinker/newPLCS7/Properties/AssemblyInfo.cs
  33. 315 0
      PLCLinker/newPLCS7/entity.cs
  34. 53 0
      PLCLinker/newPLCS7/newPLCS7.csproj
  35. BIN
      PLCLinker/newPLCS7/snap7Enc.dll
  36. 252 0
      PLCLinker/snap7Enc/Conversion.cs
  37. 181 0
      PLCLinker/snap7Enc/Enums.cs
  38. 197 0
      PLCLinker/snap7Enc/PLCAddress.cs
  39. 92 0
      PLCLinker/snap7Enc/PLCExceptions.cs
  40. 174 0
      PLCLinker/snap7Enc/Plc.cs
  41. 39 0
      PLCLinker/snap7Enc/PlcException.cs
  42. 36 0
      PLCLinker/snap7Enc/Properties/AssemblyInfo.cs
  43. 3754 0
      PLCLinker/snap7Enc/Sharp7.cs
  44. 27 0
      PLCLinker/snap7Enc/Types/Bit.cs
  45. 33 0
      PLCLinker/snap7Enc/Types/Boolean.cs
  46. 33 0
      PLCLinker/snap7Enc/Types/Byte.cs
  47. 58 0
      PLCLinker/snap7Enc/Types/ByteArray.cs
  48. 344 0
      PLCLinker/snap7Enc/Types/Class.cs
  49. 63 0
      PLCLinker/snap7Enc/Types/Counter.cs
  50. 65 0
      PLCLinker/snap7Enc/Types/DInt.cs
  51. 73 0
      PLCLinker/snap7Enc/Types/DWord.cs
  52. 91 0
      PLCLinker/snap7Enc/Types/DataItem.cs
  53. 91 0
      PLCLinker/snap7Enc/Types/Double.cs
  54. 87 0
      PLCLinker/snap7Enc/Types/Int.cs
  55. 91 0
      PLCLinker/snap7Enc/Types/Single.cs
  56. 37 0
      PLCLinker/snap7Enc/Types/String.cs
  57. 50 0
      PLCLinker/snap7Enc/Types/StringEx.cs
  58. 271 0
      PLCLinker/snap7Enc/Types/Struct.cs
  59. 82 0
      PLCLinker/snap7Enc/Types/Timer.cs
  60. 71 0
      PLCLinker/snap7Enc/Types/Word.cs
  61. 71 0
      PLCLinker/snap7Enc/snap7Enc.csproj

+ 20 - 2
PLCLinker/CentralController.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2026
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PLCLinker", "PLCLinker\PLCLinker.csproj", "{2091F0C4-06F2-403A-B660-28E98344309D}"
 EndProject
@@ -13,6 +13,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "socketTest", "socketTest\so
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PLCConnector", "PLCConnector\PLCConnector.csproj", "{12254714-E07B-4514-BD5B-EDD0A2C71D62}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "newPLCConnector", "newPLCConnector\newPLCConnector.csproj", "{D8626935-71C8-423E-AAD7-D2BDBA809575}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "newPLCS7", "newPLCS7\newPLCS7.csproj", "{A2B15176-879A-4D50-B0CB-D63A0CF2E384}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "snap7Enc", "snap7Enc\snap7Enc.csproj", "{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -39,6 +45,18 @@ Global
 		{12254714-E07B-4514-BD5B-EDD0A2C71D62}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{12254714-E07B-4514-BD5B-EDD0A2C71D62}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{12254714-E07B-4514-BD5B-EDD0A2C71D62}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D8626935-71C8-423E-AAD7-D2BDBA809575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D8626935-71C8-423E-AAD7-D2BDBA809575}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D8626935-71C8-423E-AAD7-D2BDBA809575}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D8626935-71C8-423E-AAD7-D2BDBA809575}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A2B15176-879A-4D50-B0CB-D63A0CF2E384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A2B15176-879A-4D50-B0CB-D63A0CF2E384}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A2B15176-879A-4D50-B0CB-D63A0CF2E384}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A2B15176-879A-4D50-B0CB-D63A0CF2E384}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 1 - 1
PLCLinker/centralController/FormNumberMachinePreview.Designer.cs

@@ -37,7 +37,7 @@
             this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
             this.ClientSize = new System.Drawing.Size(530, 390);
             this.Name = "FormNumberMachinePreview";
-            this.Text = "FormNumberMachinePreview";
+            this.Text = "号牌机预览";
             this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNumberMachinePreview_FormClosing);
             this.ResumeLayout(false);
 

+ 1 - 1
PLCLinker/centralController/FormPLCConf.Designer.cs

@@ -399,7 +399,7 @@
             this.Controls.Add(this.groupBox2);
             this.Controls.Add(this.groupBox1);
             this.Name = "FormPLCConf";
-            this.Text = "Form1";
+            this.Text = "PLC调试工具";
             this.groupBox1.ResumeLayout(false);
             this.groupBox1.PerformLayout();
             this.groupBox2.ResumeLayout(false);

+ 413 - 413
PLCLinker/centralController/FormRecordsManager.Designer.cs

@@ -28,9 +28,31 @@
         /// </summary>
         private void InitializeComponent()
         {
-            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
-            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
             this.stc_recordManager = new DevComponents.DotNetBar.SuperTabControl();
+            this.superTabControlPanel2 = new DevComponents.DotNetBar.SuperTabControlPanel();
+            this.tlp_orderRecords = new System.Windows.Forms.TableLayoutPanel();
+            this.dgvx_orderRecords = new DevComponents.DotNetBar.Controls.DataGridViewX();
+            this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn8 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.预约状态 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
+            this.dtp_endDate2 = new System.Windows.Forms.DateTimePicker();
+            this.labelX3 = new DevComponents.DotNetBar.LabelX();
+            this.labelX4 = new DevComponents.DotNetBar.LabelX();
+            this.btnx_orderRecordSearch = new DevComponents.DotNetBar.ButtonX();
+            this.btn_orderRecordExport = new DevComponents.DotNetBar.ButtonX();
+            this.labelX5 = new DevComponents.DotNetBar.LabelX();
+            this.tb_license2 = new System.Windows.Forms.TextBox();
+            this.dtp_startDate2 = new System.Windows.Forms.DateTimePicker();
+            this.sti_orderRecords = new DevComponents.DotNetBar.SuperTabItem();
             this.superTabControlPanel1 = new DevComponents.DotNetBar.SuperTabControlPanel();
             this.tlp_parkingRecord = new System.Windows.Forms.TableLayoutPanel();
             this.dgvx_parkingRecords = new DevComponents.DotNetBar.Controls.DataGridViewX();
@@ -56,38 +78,16 @@
             this.superTabControlPanel3 = new DevComponents.DotNetBar.SuperTabControlPanel();
             this.sti_dailySummary = new DevComponents.DotNetBar.SuperTabItem();
             this.sti_carRecords = new DevComponents.DotNetBar.SuperTabItem();
-            this.sti_orderRecords = new DevComponents.DotNetBar.SuperTabItem();
-            this.superTabControlPanel2 = new DevComponents.DotNetBar.SuperTabControlPanel();
-            this.tlp_orderRecords = new System.Windows.Forms.TableLayoutPanel();
-            this.dgvx_orderRecords = new DevComponents.DotNetBar.Controls.DataGridViewX();
-            this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
-            this.dtp_endDate2 = new System.Windows.Forms.DateTimePicker();
-            this.labelX3 = new DevComponents.DotNetBar.LabelX();
-            this.labelX4 = new DevComponents.DotNetBar.LabelX();
-            this.btnx_orderRecordSearch = new DevComponents.DotNetBar.ButtonX();
-            this.btn_orderRecordExport = new DevComponents.DotNetBar.ButtonX();
-            this.labelX5 = new DevComponents.DotNetBar.LabelX();
-            this.tb_license2 = new System.Windows.Forms.TextBox();
-            this.dtp_startDate2 = new System.Windows.Forms.DateTimePicker();
-            this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn8 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.预约状态 = new System.Windows.Forms.DataGridViewTextBoxColumn();
             ((System.ComponentModel.ISupportInitialize)(this.stc_recordManager)).BeginInit();
             this.stc_recordManager.SuspendLayout();
-            this.superTabControlPanel1.SuspendLayout();
-            this.tlp_parkingRecord.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.dgvx_parkingRecords)).BeginInit();
-            this.tableLayoutPanel1.SuspendLayout();
             this.superTabControlPanel2.SuspendLayout();
             this.tlp_orderRecords.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.dgvx_orderRecords)).BeginInit();
             this.tableLayoutPanel3.SuspendLayout();
+            this.superTabControlPanel1.SuspendLayout();
+            this.tlp_parkingRecord.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.dgvx_parkingRecords)).BeginInit();
+            this.tableLayoutPanel1.SuspendLayout();
             this.SuspendLayout();
             // 
             // stc_recordManager
@@ -107,8 +107,8 @@
             this.stc_recordManager.ControlBox.SubItems.AddRange(new DevComponents.DotNetBar.BaseItem[] {
             this.stc_recordManager.ControlBox.MenuBox,
             this.stc_recordManager.ControlBox.CloseBox});
-            this.stc_recordManager.Controls.Add(this.superTabControlPanel2);
             this.stc_recordManager.Controls.Add(this.superTabControlPanel1);
+            this.stc_recordManager.Controls.Add(this.superTabControlPanel2);
             this.stc_recordManager.Controls.Add(this.superTabControlPanel3);
             this.stc_recordManager.Dock = System.Windows.Forms.DockStyle.Fill;
             this.stc_recordManager.Location = new System.Drawing.Point(0, 0);
@@ -126,149 +126,412 @@
             this.sti_dailySummary});
             this.stc_recordManager.Text = "superTabControl1";
             // 
-            // superTabControlPanel1
+            // superTabControlPanel2
             // 
-            this.superTabControlPanel1.Controls.Add(this.tlp_parkingRecord);
-            this.superTabControlPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.superTabControlPanel1.Location = new System.Drawing.Point(99, 0);
-            this.superTabControlPanel1.Name = "superTabControlPanel1";
-            this.superTabControlPanel1.Size = new System.Drawing.Size(932, 481);
-            this.superTabControlPanel1.TabIndex = 1;
-            this.superTabControlPanel1.TabItem = this.sti_parkingRecords;
+            this.superTabControlPanel2.Controls.Add(this.tlp_orderRecords);
+            this.superTabControlPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.superTabControlPanel2.Location = new System.Drawing.Point(99, 0);
+            this.superTabControlPanel2.Name = "superTabControlPanel2";
+            this.superTabControlPanel2.Size = new System.Drawing.Size(932, 481);
+            this.superTabControlPanel2.TabIndex = 0;
+            this.superTabControlPanel2.TabItem = this.sti_orderRecords;
             // 
-            // tlp_parkingRecord
+            // tlp_orderRecords
             // 
-            this.tlp_parkingRecord.ColumnCount = 1;
-            this.tlp_parkingRecord.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
-            this.tlp_parkingRecord.Controls.Add(this.dgvx_parkingRecords, 0, 1);
-            this.tlp_parkingRecord.Controls.Add(this.tableLayoutPanel1, 0, 0);
-            this.tlp_parkingRecord.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.tlp_parkingRecord.Location = new System.Drawing.Point(0, 0);
-            this.tlp_parkingRecord.Name = "tlp_parkingRecord";
-            this.tlp_parkingRecord.RowCount = 2;
-            this.tlp_parkingRecord.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F));
-            this.tlp_parkingRecord.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 85F));
-            this.tlp_parkingRecord.Size = new System.Drawing.Size(932, 481);
-            this.tlp_parkingRecord.TabIndex = 2;
+            this.tlp_orderRecords.ColumnCount = 1;
+            this.tlp_orderRecords.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tlp_orderRecords.Controls.Add(this.dgvx_orderRecords, 0, 1);
+            this.tlp_orderRecords.Controls.Add(this.tableLayoutPanel3, 0, 0);
+            this.tlp_orderRecords.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tlp_orderRecords.Location = new System.Drawing.Point(0, 0);
+            this.tlp_orderRecords.Name = "tlp_orderRecords";
+            this.tlp_orderRecords.RowCount = 2;
+            this.tlp_orderRecords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F));
+            this.tlp_orderRecords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 85F));
+            this.tlp_orderRecords.Size = new System.Drawing.Size(932, 481);
+            this.tlp_orderRecords.TabIndex = 3;
             // 
-            // dgvx_parkingRecords
+            // dgvx_orderRecords
             // 
-            this.dgvx_parkingRecords.BackgroundColor = System.Drawing.SystemColors.ActiveCaption;
-            this.dgvx_parkingRecords.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-            this.dgvx_parkingRecords.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
-            this.parkingRecordsID,
-            this.userID,
-            this.numberPlate,
-            this.parkingSpaceID,
-            this.realParkTime,
-            this.realGetTime,
-            this.receiptNum,
-            this.parkingPrice,
-            this.paymentStatus});
-            dataGridViewCellStyle4.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
-            dataGridViewCellStyle4.BackColor = System.Drawing.SystemColors.Window;
-            dataGridViewCellStyle4.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            dataGridViewCellStyle4.ForeColor = System.Drawing.SystemColors.ControlText;
-            dataGridViewCellStyle4.SelectionBackColor = System.Drawing.SystemColors.Highlight;
-            dataGridViewCellStyle4.SelectionForeColor = System.Drawing.SystemColors.ControlText;
-            dataGridViewCellStyle4.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
-            this.dgvx_parkingRecords.DefaultCellStyle = dataGridViewCellStyle4;
-            this.dgvx_parkingRecords.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.dgvx_parkingRecords.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(208)))), ((int)(((byte)(215)))), ((int)(((byte)(229)))));
-            this.dgvx_parkingRecords.Location = new System.Drawing.Point(3, 75);
-            this.dgvx_parkingRecords.MinimumSize = new System.Drawing.Size(389, 0);
-            this.dgvx_parkingRecords.Name = "dgvx_parkingRecords";
-            this.dgvx_parkingRecords.RowTemplate.Height = 23;
-            this.dgvx_parkingRecords.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
-            this.dgvx_parkingRecords.Size = new System.Drawing.Size(926, 403);
-            this.dgvx_parkingRecords.TabIndex = 1;
+            this.dgvx_orderRecords.BackgroundColor = System.Drawing.SystemColors.ActiveCaption;
+            this.dgvx_orderRecords.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dgvx_orderRecords.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.dataGridViewTextBoxColumn1,
+            this.dataGridViewTextBoxColumn2,
+            this.dataGridViewTextBoxColumn3,
+            this.dataGridViewTextBoxColumn5,
+            this.dataGridViewTextBoxColumn6,
+            this.dataGridViewTextBoxColumn7,
+            this.dataGridViewTextBoxColumn8,
+            this.dataGridViewTextBoxColumn9,
+            this.预约状态});
+            dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+            dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
+            dataGridViewCellStyle2.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
+            dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
+            dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.ControlText;
+            dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+            this.dgvx_orderRecords.DefaultCellStyle = dataGridViewCellStyle2;
+            this.dgvx_orderRecords.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.dgvx_orderRecords.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(208)))), ((int)(((byte)(215)))), ((int)(((byte)(229)))));
+            this.dgvx_orderRecords.Location = new System.Drawing.Point(3, 75);
+            this.dgvx_orderRecords.MinimumSize = new System.Drawing.Size(389, 0);
+            this.dgvx_orderRecords.Name = "dgvx_orderRecords";
+            this.dgvx_orderRecords.RowTemplate.Height = 23;
+            this.dgvx_orderRecords.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+            this.dgvx_orderRecords.Size = new System.Drawing.Size(926, 403);
+            this.dgvx_orderRecords.TabIndex = 1;
             // 
-            // parkingRecordsID
+            // dataGridViewTextBoxColumn1
             // 
-            this.parkingRecordsID.HeaderText = "停车记录ID";
-            this.parkingRecordsID.MaxInputLength = 11;
-            this.parkingRecordsID.Name = "parkingRecordsID";
-            this.parkingRecordsID.ReadOnly = true;
-            this.parkingRecordsID.Width = 90;
+            this.dataGridViewTextBoxColumn1.HeaderText = "预约记录ID";
+            this.dataGridViewTextBoxColumn1.MaxInputLength = 11;
+            this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
+            this.dataGridViewTextBoxColumn1.ReadOnly = true;
+            this.dataGridViewTextBoxColumn1.Width = 90;
             // 
-            // userID
+            // dataGridViewTextBoxColumn2
             // 
-            this.userID.HeaderText = "用户ID";
-            this.userID.MaxInputLength = 8;
-            this.userID.Name = "userID";
-            this.userID.ReadOnly = true;
-            this.userID.Width = 70;
+            this.dataGridViewTextBoxColumn2.HeaderText = "用户ID";
+            this.dataGridViewTextBoxColumn2.MaxInputLength = 8;
+            this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
+            this.dataGridViewTextBoxColumn2.ReadOnly = true;
+            this.dataGridViewTextBoxColumn2.Width = 70;
             // 
-            // numberPlate
+            // dataGridViewTextBoxColumn3
             // 
-            this.numberPlate.HeaderText = "号牌";
-            this.numberPlate.MaxInputLength = 9;
-            this.numberPlate.Name = "numberPlate";
-            this.numberPlate.ReadOnly = true;
-            this.numberPlate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.numberPlate.Width = 80;
+            this.dataGridViewTextBoxColumn3.HeaderText = "号牌";
+            this.dataGridViewTextBoxColumn3.MaxInputLength = 9;
+            this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
+            this.dataGridViewTextBoxColumn3.ReadOnly = true;
+            this.dataGridViewTextBoxColumn3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn3.Width = 80;
             // 
-            // parkingSpaceID
+            // dataGridViewTextBoxColumn5
             // 
-            this.parkingSpaceID.HeaderText = "车位编号";
-            this.parkingSpaceID.MaxInputLength = 4;
-            this.parkingSpaceID.Name = "parkingSpaceID";
-            this.parkingSpaceID.ReadOnly = true;
-            this.parkingSpaceID.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.parkingSpaceID.Width = 80;
+            this.dataGridViewTextBoxColumn5.HeaderText = "停车预约时间";
+            this.dataGridViewTextBoxColumn5.MaxInputLength = 50;
+            this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
+            this.dataGridViewTextBoxColumn5.ReadOnly = true;
+            this.dataGridViewTextBoxColumn5.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn5.Width = 140;
             // 
-            // realParkTime
+            // dataGridViewTextBoxColumn6
             // 
-            this.realParkTime.HeaderText = "实际停入时间";
-            this.realParkTime.MaxInputLength = 50;
-            this.realParkTime.Name = "realParkTime";
-            this.realParkTime.ReadOnly = true;
-            this.realParkTime.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.realParkTime.Width = 140;
+            this.dataGridViewTextBoxColumn6.HeaderText = "停车预约取消时间";
+            this.dataGridViewTextBoxColumn6.MaxInputLength = 50;
+            this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
+            this.dataGridViewTextBoxColumn6.ReadOnly = true;
+            this.dataGridViewTextBoxColumn6.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn6.Width = 140;
             // 
-            // realGetTime
+            // dataGridViewTextBoxColumn7
             // 
-            this.realGetTime.HeaderText = "实际取出时间";
-            this.realGetTime.MaxInputLength = 50;
-            this.realGetTime.Name = "realGetTime";
-            this.realGetTime.ReadOnly = true;
-            this.realGetTime.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.realGetTime.Width = 140;
+            this.dataGridViewTextBoxColumn7.HeaderText = "预约取车时间";
+            this.dataGridViewTextBoxColumn7.MaxInputLength = 50;
+            this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7";
+            this.dataGridViewTextBoxColumn7.ReadOnly = true;
+            this.dataGridViewTextBoxColumn7.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
             // 
-            // receiptNum
+            // dataGridViewTextBoxColumn8
             // 
-            this.receiptNum.HeaderText = "凭证号";
-            this.receiptNum.MaxInputLength = 8;
-            this.receiptNum.Name = "receiptNum";
-            this.receiptNum.ReadOnly = true;
-            this.receiptNum.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn8.HeaderText = "预约时长";
+            this.dataGridViewTextBoxColumn8.MaxInputLength = 11;
+            this.dataGridViewTextBoxColumn8.Name = "dataGridViewTextBoxColumn8";
+            this.dataGridViewTextBoxColumn8.ReadOnly = true;
+            this.dataGridViewTextBoxColumn8.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
             // 
-            // parkingPrice
+            // dataGridViewTextBoxColumn9
             // 
-            this.parkingPrice.HeaderText = "停车费用";
-            this.parkingPrice.MaxInputLength = 11;
-            this.parkingPrice.Name = "parkingPrice";
-            this.parkingPrice.ReadOnly = true;
-            this.parkingPrice.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn9.HeaderText = "预约费用";
+            this.dataGridViewTextBoxColumn9.MaxInputLength = 11;
+            this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9";
+            this.dataGridViewTextBoxColumn9.ReadOnly = true;
             // 
-            // paymentStatus
+            // 预约状态
             // 
-            this.paymentStatus.HeaderText = "收费状态";
-            this.paymentStatus.MaxInputLength = 11;
-            this.paymentStatus.Name = "paymentStatus";
-            this.paymentStatus.ReadOnly = true;
+            this.预约状态.HeaderText = "预约状态";
+            this.预约状态.MaxInputLength = 8;
+            this.预约状态.Name = "预约状态";
+            this.预约状态.ReadOnly = true;
             // 
-            // tableLayoutPanel1
+            // tableLayoutPanel3
             // 
-            this.tableLayoutPanel1.ColumnCount = 8;
-            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+            this.tableLayoutPanel3.ColumnCount = 8;
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 87F));
+            this.tableLayoutPanel3.Controls.Add(this.dtp_endDate2, 3, 0);
+            this.tableLayoutPanel3.Controls.Add(this.labelX3, 0, 0);
+            this.tableLayoutPanel3.Controls.Add(this.labelX4, 2, 0);
+            this.tableLayoutPanel3.Controls.Add(this.btnx_orderRecordSearch, 6, 0);
+            this.tableLayoutPanel3.Controls.Add(this.btn_orderRecordExport, 7, 0);
+            this.tableLayoutPanel3.Controls.Add(this.labelX5, 4, 0);
+            this.tableLayoutPanel3.Controls.Add(this.tb_license2, 5, 0);
+            this.tableLayoutPanel3.Controls.Add(this.dtp_startDate2, 1, 0);
+            this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tableLayoutPanel3.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 3);
+            this.tableLayoutPanel3.Name = "tableLayoutPanel3";
+            this.tableLayoutPanel3.RowCount = 1;
+            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel3.Size = new System.Drawing.Size(926, 66);
+            this.tableLayoutPanel3.TabIndex = 2;
+            // 
+            // dtp_endDate2
+            // 
+            this.dtp_endDate2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+            this.dtp_endDate2.CalendarFont = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.dtp_endDate2.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.dtp_endDate2.Location = new System.Drawing.Point(341, 20);
+            this.dtp_endDate2.Name = "dtp_endDate2";
+            this.dtp_endDate2.Size = new System.Drawing.Size(162, 26);
+            this.dtp_endDate2.TabIndex = 12;
+            // 
+            // labelX3
+            // 
+            // 
+            // 
+            // 
+            this.labelX3.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.labelX3.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.labelX3.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.labelX3.Location = new System.Drawing.Point(3, 3);
+            this.labelX3.Name = "labelX3";
+            this.labelX3.Size = new System.Drawing.Size(79, 60);
+            this.labelX3.TabIndex = 3;
+            this.labelX3.Text = "起始日期:";
+            // 
+            // labelX4
+            // 
+            // 
+            // 
+            // 
+            this.labelX4.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.labelX4.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.labelX4.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.labelX4.Location = new System.Drawing.Point(256, 3);
+            this.labelX4.Name = "labelX4";
+            this.labelX4.Size = new System.Drawing.Size(79, 60);
+            this.labelX4.TabIndex = 4;
+            this.labelX4.Text = "截止日期:";
+            // 
+            // btnx_orderRecordSearch
+            // 
+            this.btnx_orderRecordSearch.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
+            this.btnx_orderRecordSearch.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            this.btnx_orderRecordSearch.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
+            this.btnx_orderRecordSearch.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.btnx_orderRecordSearch.Location = new System.Drawing.Point(761, 15);
+            this.btnx_orderRecordSearch.Name = "btnx_orderRecordSearch";
+            this.btnx_orderRecordSearch.Size = new System.Drawing.Size(74, 35);
+            this.btnx_orderRecordSearch.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
+            this.btnx_orderRecordSearch.TabIndex = 7;
+            this.btnx_orderRecordSearch.Text = "查询";
+            this.btnx_orderRecordSearch.Click += new System.EventHandler(this.btnx_orderRecordSearch_Click);
+            // 
+            // btn_orderRecordExport
+            // 
+            this.btn_orderRecordExport.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
+            this.btn_orderRecordExport.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            this.btn_orderRecordExport.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
+            this.btn_orderRecordExport.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.btn_orderRecordExport.Location = new System.Drawing.Point(841, 15);
+            this.btn_orderRecordExport.Name = "btn_orderRecordExport";
+            this.btn_orderRecordExport.Size = new System.Drawing.Size(75, 35);
+            this.btn_orderRecordExport.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
+            this.btn_orderRecordExport.TabIndex = 8;
+            this.btn_orderRecordExport.Text = "导出";
+            this.btn_orderRecordExport.Click += new System.EventHandler(this.btn_orderRecordExport_Click);
+            // 
+            // labelX5
+            // 
+            // 
+            // 
+            // 
+            this.labelX5.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.labelX5.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.labelX5.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.labelX5.Location = new System.Drawing.Point(509, 3);
+            this.labelX5.Name = "labelX5";
+            this.labelX5.Size = new System.Drawing.Size(79, 60);
+            this.labelX5.TabIndex = 9;
+            this.labelX5.Text = "车辆号牌:";
+            // 
+            // tb_license2
+            // 
+            this.tb_license2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+            this.tb_license2.Location = new System.Drawing.Point(594, 20);
+            this.tb_license2.Name = "tb_license2";
+            this.tb_license2.Size = new System.Drawing.Size(161, 26);
+            this.tb_license2.TabIndex = 10;
+            // 
+            // dtp_startDate2
+            // 
+            this.dtp_startDate2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+            this.dtp_startDate2.CalendarFont = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.dtp_startDate2.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.dtp_startDate2.Location = new System.Drawing.Point(88, 20);
+            this.dtp_startDate2.Name = "dtp_startDate2";
+            this.dtp_startDate2.Size = new System.Drawing.Size(162, 26);
+            this.dtp_startDate2.TabIndex = 11;
+            // 
+            // sti_orderRecords
+            // 
+            this.sti_orderRecords.AttachedControl = this.superTabControlPanel2;
+            this.sti_orderRecords.GlobalItem = false;
+            this.sti_orderRecords.Name = "sti_orderRecords";
+            this.sti_orderRecords.Text = "预约记录";
+            // 
+            // superTabControlPanel1
+            // 
+            this.superTabControlPanel1.Controls.Add(this.tlp_parkingRecord);
+            this.superTabControlPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.superTabControlPanel1.Location = new System.Drawing.Point(99, 0);
+            this.superTabControlPanel1.Name = "superTabControlPanel1";
+            this.superTabControlPanel1.Size = new System.Drawing.Size(932, 481);
+            this.superTabControlPanel1.TabIndex = 1;
+            this.superTabControlPanel1.TabItem = this.sti_parkingRecords;
+            // 
+            // tlp_parkingRecord
+            // 
+            this.tlp_parkingRecord.ColumnCount = 1;
+            this.tlp_parkingRecord.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tlp_parkingRecord.Controls.Add(this.dgvx_parkingRecords, 0, 1);
+            this.tlp_parkingRecord.Controls.Add(this.tableLayoutPanel1, 0, 0);
+            this.tlp_parkingRecord.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tlp_parkingRecord.Location = new System.Drawing.Point(0, 0);
+            this.tlp_parkingRecord.Name = "tlp_parkingRecord";
+            this.tlp_parkingRecord.RowCount = 2;
+            this.tlp_parkingRecord.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F));
+            this.tlp_parkingRecord.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 85F));
+            this.tlp_parkingRecord.Size = new System.Drawing.Size(932, 481);
+            this.tlp_parkingRecord.TabIndex = 2;
+            // 
+            // dgvx_parkingRecords
+            // 
+            this.dgvx_parkingRecords.BackgroundColor = System.Drawing.SystemColors.ActiveCaption;
+            this.dgvx_parkingRecords.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dgvx_parkingRecords.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.parkingRecordsID,
+            this.userID,
+            this.numberPlate,
+            this.parkingSpaceID,
+            this.realParkTime,
+            this.realGetTime,
+            this.receiptNum,
+            this.parkingPrice,
+            this.paymentStatus});
+            dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+            dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
+            dataGridViewCellStyle1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
+            dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
+            dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.ControlText;
+            dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+            this.dgvx_parkingRecords.DefaultCellStyle = dataGridViewCellStyle1;
+            this.dgvx_parkingRecords.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.dgvx_parkingRecords.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(208)))), ((int)(((byte)(215)))), ((int)(((byte)(229)))));
+            this.dgvx_parkingRecords.Location = new System.Drawing.Point(3, 75);
+            this.dgvx_parkingRecords.MinimumSize = new System.Drawing.Size(389, 0);
+            this.dgvx_parkingRecords.Name = "dgvx_parkingRecords";
+            this.dgvx_parkingRecords.RowTemplate.Height = 23;
+            this.dgvx_parkingRecords.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+            this.dgvx_parkingRecords.Size = new System.Drawing.Size(926, 403);
+            this.dgvx_parkingRecords.TabIndex = 1;
+            // 
+            // parkingRecordsID
+            // 
+            this.parkingRecordsID.HeaderText = "停车记录ID";
+            this.parkingRecordsID.MaxInputLength = 11;
+            this.parkingRecordsID.Name = "parkingRecordsID";
+            this.parkingRecordsID.ReadOnly = true;
+            this.parkingRecordsID.Width = 90;
+            // 
+            // userID
+            // 
+            this.userID.HeaderText = "用户ID";
+            this.userID.MaxInputLength = 8;
+            this.userID.Name = "userID";
+            this.userID.ReadOnly = true;
+            this.userID.Width = 70;
+            // 
+            // numberPlate
+            // 
+            this.numberPlate.HeaderText = "号牌";
+            this.numberPlate.MaxInputLength = 9;
+            this.numberPlate.Name = "numberPlate";
+            this.numberPlate.ReadOnly = true;
+            this.numberPlate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.numberPlate.Width = 80;
+            // 
+            // parkingSpaceID
+            // 
+            this.parkingSpaceID.HeaderText = "车位编号";
+            this.parkingSpaceID.MaxInputLength = 4;
+            this.parkingSpaceID.Name = "parkingSpaceID";
+            this.parkingSpaceID.ReadOnly = true;
+            this.parkingSpaceID.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.parkingSpaceID.Width = 80;
+            // 
+            // realParkTime
+            // 
+            this.realParkTime.HeaderText = "实际停入时间";
+            this.realParkTime.MaxInputLength = 50;
+            this.realParkTime.Name = "realParkTime";
+            this.realParkTime.ReadOnly = true;
+            this.realParkTime.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.realParkTime.Width = 140;
+            // 
+            // realGetTime
+            // 
+            this.realGetTime.HeaderText = "实际取出时间";
+            this.realGetTime.MaxInputLength = 50;
+            this.realGetTime.Name = "realGetTime";
+            this.realGetTime.ReadOnly = true;
+            this.realGetTime.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.realGetTime.Width = 140;
+            // 
+            // receiptNum
+            // 
+            this.receiptNum.HeaderText = "凭证号";
+            this.receiptNum.MaxInputLength = 8;
+            this.receiptNum.Name = "receiptNum";
+            this.receiptNum.ReadOnly = true;
+            this.receiptNum.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            // 
+            // parkingPrice
+            // 
+            this.parkingPrice.HeaderText = "停车费用";
+            this.parkingPrice.MaxInputLength = 11;
+            this.parkingPrice.Name = "parkingPrice";
+            this.parkingPrice.ReadOnly = true;
+            this.parkingPrice.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            // 
+            // paymentStatus
+            // 
+            this.paymentStatus.HeaderText = "收费状态";
+            this.paymentStatus.MaxInputLength = 11;
+            this.paymentStatus.Name = "paymentStatus";
+            this.paymentStatus.ReadOnly = true;
+            // 
+            // tableLayoutPanel1
+            // 
+            this.tableLayoutPanel1.ColumnCount = 8;
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
-            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 87F));
             this.tableLayoutPanel1.Controls.Add(this.dtp_endDate, 3, 0);
             this.tableLayoutPanel1.Controls.Add(this.lbx_startDate, 0, 0);
             this.tableLayoutPanel1.Controls.Add(this.labelX1, 2, 0);
@@ -330,7 +593,7 @@
             this.btnx_parkingRecordSearch.Anchor = System.Windows.Forms.AnchorStyles.Left;
             this.btnx_parkingRecordSearch.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
             this.btnx_parkingRecordSearch.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btnx_parkingRecordSearch.Location = new System.Drawing.Point(762, 15);
+            this.btnx_parkingRecordSearch.Location = new System.Drawing.Point(761, 15);
             this.btnx_parkingRecordSearch.Name = "btnx_parkingRecordSearch";
             this.btnx_parkingRecordSearch.Size = new System.Drawing.Size(74, 35);
             this.btnx_parkingRecordSearch.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
@@ -344,7 +607,7 @@
             this.btnx_parkingRecordExport.Anchor = System.Windows.Forms.AnchorStyles.Left;
             this.btnx_parkingRecordExport.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
             this.btnx_parkingRecordExport.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btnx_parkingRecordExport.Location = new System.Drawing.Point(842, 15);
+            this.btnx_parkingRecordExport.Location = new System.Drawing.Point(841, 15);
             this.btnx_parkingRecordExport.Name = "btnx_parkingRecordExport";
             this.btnx_parkingRecordExport.Size = new System.Drawing.Size(75, 35);
             this.btnx_parkingRecordExport.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
@@ -371,7 +634,7 @@
             this.tb_license.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
             this.tb_license.Location = new System.Drawing.Point(594, 20);
             this.tb_license.Name = "tb_license";
-            this.tb_license.Size = new System.Drawing.Size(162, 26);
+            this.tb_license.Size = new System.Drawing.Size(161, 26);
             this.tb_license.TabIndex = 10;
             // 
             // dtp_startDate
@@ -413,269 +676,6 @@
             this.sti_carRecords.Name = "sti_carRecords";
             this.sti_carRecords.Text = "车辆停取记录";
             // 
-            // sti_orderRecords
-            // 
-            this.sti_orderRecords.AttachedControl = this.superTabControlPanel2;
-            this.sti_orderRecords.GlobalItem = false;
-            this.sti_orderRecords.Name = "sti_orderRecords";
-            this.sti_orderRecords.Text = "预约记录";
-            // 
-            // superTabControlPanel2
-            // 
-            this.superTabControlPanel2.Controls.Add(this.tlp_orderRecords);
-            this.superTabControlPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.superTabControlPanel2.Location = new System.Drawing.Point(99, 0);
-            this.superTabControlPanel2.Name = "superTabControlPanel2";
-            this.superTabControlPanel2.Size = new System.Drawing.Size(932, 481);
-            this.superTabControlPanel2.TabIndex = 0;
-            this.superTabControlPanel2.TabItem = this.sti_orderRecords;
-            // 
-            // tlp_orderRecords
-            // 
-            this.tlp_orderRecords.ColumnCount = 1;
-            this.tlp_orderRecords.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
-            this.tlp_orderRecords.Controls.Add(this.dgvx_orderRecords, 0, 1);
-            this.tlp_orderRecords.Controls.Add(this.tableLayoutPanel3, 0, 0);
-            this.tlp_orderRecords.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.tlp_orderRecords.Location = new System.Drawing.Point(0, 0);
-            this.tlp_orderRecords.Name = "tlp_orderRecords";
-            this.tlp_orderRecords.RowCount = 2;
-            this.tlp_orderRecords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F));
-            this.tlp_orderRecords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 85F));
-            this.tlp_orderRecords.Size = new System.Drawing.Size(932, 481);
-            this.tlp_orderRecords.TabIndex = 3;
-            // 
-            // dgvx_orderRecords
-            // 
-            this.dgvx_orderRecords.BackgroundColor = System.Drawing.SystemColors.ActiveCaption;
-            this.dgvx_orderRecords.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-            this.dgvx_orderRecords.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
-            this.dataGridViewTextBoxColumn1,
-            this.dataGridViewTextBoxColumn2,
-            this.dataGridViewTextBoxColumn3,
-            this.dataGridViewTextBoxColumn5,
-            this.dataGridViewTextBoxColumn6,
-            this.dataGridViewTextBoxColumn7,
-            this.dataGridViewTextBoxColumn8,
-            this.dataGridViewTextBoxColumn9,
-            this.预约状态});
-            dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
-            dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Window;
-            dataGridViewCellStyle3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.ControlText;
-            dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
-            dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.ControlText;
-            dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
-            this.dgvx_orderRecords.DefaultCellStyle = dataGridViewCellStyle3;
-            this.dgvx_orderRecords.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.dgvx_orderRecords.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(208)))), ((int)(((byte)(215)))), ((int)(((byte)(229)))));
-            this.dgvx_orderRecords.Location = new System.Drawing.Point(3, 75);
-            this.dgvx_orderRecords.MinimumSize = new System.Drawing.Size(389, 0);
-            this.dgvx_orderRecords.Name = "dgvx_orderRecords";
-            this.dgvx_orderRecords.RowTemplate.Height = 23;
-            this.dgvx_orderRecords.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
-            this.dgvx_orderRecords.Size = new System.Drawing.Size(926, 403);
-            this.dgvx_orderRecords.TabIndex = 1;
-            // 
-            // tableLayoutPanel3
-            // 
-            this.tableLayoutPanel3.ColumnCount = 8;
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
-            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 85F));
-            this.tableLayoutPanel3.Controls.Add(this.dtp_endDate2, 3, 0);
-            this.tableLayoutPanel3.Controls.Add(this.labelX3, 0, 0);
-            this.tableLayoutPanel3.Controls.Add(this.labelX4, 2, 0);
-            this.tableLayoutPanel3.Controls.Add(this.btnx_orderRecordSearch, 6, 0);
-            this.tableLayoutPanel3.Controls.Add(this.btn_orderRecordExport, 7, 0);
-            this.tableLayoutPanel3.Controls.Add(this.labelX5, 4, 0);
-            this.tableLayoutPanel3.Controls.Add(this.tb_license2, 5, 0);
-            this.tableLayoutPanel3.Controls.Add(this.dtp_startDate2, 1, 0);
-            this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.tableLayoutPanel3.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 3);
-            this.tableLayoutPanel3.Name = "tableLayoutPanel3";
-            this.tableLayoutPanel3.RowCount = 1;
-            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
-            this.tableLayoutPanel3.Size = new System.Drawing.Size(926, 66);
-            this.tableLayoutPanel3.TabIndex = 2;
-            // 
-            // dtp_endDate2
-            // 
-            this.dtp_endDate2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
-            this.dtp_endDate2.CalendarFont = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.dtp_endDate2.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.dtp_endDate2.Location = new System.Drawing.Point(341, 20);
-            this.dtp_endDate2.Name = "dtp_endDate2";
-            this.dtp_endDate2.Size = new System.Drawing.Size(162, 26);
-            this.dtp_endDate2.TabIndex = 12;
-            // 
-            // labelX3
-            // 
-            // 
-            // 
-            // 
-            this.labelX3.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.labelX3.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.labelX3.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.labelX3.Location = new System.Drawing.Point(3, 3);
-            this.labelX3.Name = "labelX3";
-            this.labelX3.Size = new System.Drawing.Size(79, 60);
-            this.labelX3.TabIndex = 3;
-            this.labelX3.Text = "起始日期:";
-            // 
-            // labelX4
-            // 
-            // 
-            // 
-            // 
-            this.labelX4.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.labelX4.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.labelX4.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.labelX4.Location = new System.Drawing.Point(256, 3);
-            this.labelX4.Name = "labelX4";
-            this.labelX4.Size = new System.Drawing.Size(79, 60);
-            this.labelX4.TabIndex = 4;
-            this.labelX4.Text = "截止日期:";
-            // 
-            // btnx_orderRecordSearch
-            // 
-            this.btnx_orderRecordSearch.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
-            this.btnx_orderRecordSearch.Anchor = System.Windows.Forms.AnchorStyles.Left;
-            this.btnx_orderRecordSearch.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
-            this.btnx_orderRecordSearch.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btnx_orderRecordSearch.Location = new System.Drawing.Point(762, 15);
-            this.btnx_orderRecordSearch.Name = "btnx_orderRecordSearch";
-            this.btnx_orderRecordSearch.Size = new System.Drawing.Size(74, 35);
-            this.btnx_orderRecordSearch.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
-            this.btnx_orderRecordSearch.TabIndex = 7;
-            this.btnx_orderRecordSearch.Text = "查询";
-            this.btnx_orderRecordSearch.Click += new System.EventHandler(this.btnx_orderRecordSearch_Click);
-            // 
-            // btn_orderRecordExport
-            // 
-            this.btn_orderRecordExport.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
-            this.btn_orderRecordExport.Anchor = System.Windows.Forms.AnchorStyles.Left;
-            this.btn_orderRecordExport.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
-            this.btn_orderRecordExport.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btn_orderRecordExport.Location = new System.Drawing.Point(842, 15);
-            this.btn_orderRecordExport.Name = "btn_orderRecordExport";
-            this.btn_orderRecordExport.Size = new System.Drawing.Size(75, 35);
-            this.btn_orderRecordExport.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
-            this.btn_orderRecordExport.TabIndex = 8;
-            this.btn_orderRecordExport.Text = "导出";
-            this.btn_orderRecordExport.Click += new System.EventHandler(this.btn_orderRecordExport_Click);
-            // 
-            // labelX5
-            // 
-            // 
-            // 
-            // 
-            this.labelX5.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.labelX5.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.labelX5.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.labelX5.Location = new System.Drawing.Point(509, 3);
-            this.labelX5.Name = "labelX5";
-            this.labelX5.Size = new System.Drawing.Size(79, 60);
-            this.labelX5.TabIndex = 9;
-            this.labelX5.Text = "车辆号牌:";
-            // 
-            // tb_license2
-            // 
-            this.tb_license2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
-            this.tb_license2.Location = new System.Drawing.Point(594, 20);
-            this.tb_license2.Name = "tb_license2";
-            this.tb_license2.Size = new System.Drawing.Size(162, 26);
-            this.tb_license2.TabIndex = 10;
-            // 
-            // dtp_startDate2
-            // 
-            this.dtp_startDate2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
-            this.dtp_startDate2.CalendarFont = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.dtp_startDate2.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.dtp_startDate2.Location = new System.Drawing.Point(88, 20);
-            this.dtp_startDate2.Name = "dtp_startDate2";
-            this.dtp_startDate2.Size = new System.Drawing.Size(162, 26);
-            this.dtp_startDate2.TabIndex = 11;
-            // 
-            // dataGridViewTextBoxColumn1
-            // 
-            this.dataGridViewTextBoxColumn1.HeaderText = "预约记录ID";
-            this.dataGridViewTextBoxColumn1.MaxInputLength = 11;
-            this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
-            this.dataGridViewTextBoxColumn1.ReadOnly = true;
-            this.dataGridViewTextBoxColumn1.Width = 90;
-            // 
-            // dataGridViewTextBoxColumn2
-            // 
-            this.dataGridViewTextBoxColumn2.HeaderText = "用户ID";
-            this.dataGridViewTextBoxColumn2.MaxInputLength = 8;
-            this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
-            this.dataGridViewTextBoxColumn2.ReadOnly = true;
-            this.dataGridViewTextBoxColumn2.Width = 70;
-            // 
-            // dataGridViewTextBoxColumn3
-            // 
-            this.dataGridViewTextBoxColumn3.HeaderText = "号牌";
-            this.dataGridViewTextBoxColumn3.MaxInputLength = 9;
-            this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
-            this.dataGridViewTextBoxColumn3.ReadOnly = true;
-            this.dataGridViewTextBoxColumn3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.dataGridViewTextBoxColumn3.Width = 80;
-            // 
-            // dataGridViewTextBoxColumn5
-            // 
-            this.dataGridViewTextBoxColumn5.HeaderText = "停车预约时间";
-            this.dataGridViewTextBoxColumn5.MaxInputLength = 50;
-            this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5";
-            this.dataGridViewTextBoxColumn5.ReadOnly = true;
-            this.dataGridViewTextBoxColumn5.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.dataGridViewTextBoxColumn5.Width = 140;
-            // 
-            // dataGridViewTextBoxColumn6
-            // 
-            this.dataGridViewTextBoxColumn6.HeaderText = "停车预约取消时间";
-            this.dataGridViewTextBoxColumn6.MaxInputLength = 50;
-            this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6";
-            this.dataGridViewTextBoxColumn6.ReadOnly = true;
-            this.dataGridViewTextBoxColumn6.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            this.dataGridViewTextBoxColumn6.Width = 140;
-            // 
-            // dataGridViewTextBoxColumn7
-            // 
-            this.dataGridViewTextBoxColumn7.HeaderText = "预约取车时间";
-            this.dataGridViewTextBoxColumn7.MaxInputLength = 50;
-            this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7";
-            this.dataGridViewTextBoxColumn7.ReadOnly = true;
-            this.dataGridViewTextBoxColumn7.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            // 
-            // dataGridViewTextBoxColumn8
-            // 
-            this.dataGridViewTextBoxColumn8.HeaderText = "预约时长";
-            this.dataGridViewTextBoxColumn8.MaxInputLength = 11;
-            this.dataGridViewTextBoxColumn8.Name = "dataGridViewTextBoxColumn8";
-            this.dataGridViewTextBoxColumn8.ReadOnly = true;
-            this.dataGridViewTextBoxColumn8.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
-            // 
-            // dataGridViewTextBoxColumn9
-            // 
-            this.dataGridViewTextBoxColumn9.HeaderText = "预约费用";
-            this.dataGridViewTextBoxColumn9.MaxInputLength = 11;
-            this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9";
-            this.dataGridViewTextBoxColumn9.ReadOnly = true;
-            // 
-            // 预约状态
-            // 
-            this.预约状态.HeaderText = "预约状态";
-            this.预约状态.MaxInputLength = 8;
-            this.预约状态.Name = "预约状态";
-            this.预约状态.ReadOnly = true;
-            // 
             // FormRecordsManager
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -683,19 +683,19 @@
             this.ClientSize = new System.Drawing.Size(1031, 481);
             this.Controls.Add(this.stc_recordManager);
             this.Name = "FormRecordsManager";
-            this.Text = "FormRecordsManager";
+            this.Text = "记录管理器";
             ((System.ComponentModel.ISupportInitialize)(this.stc_recordManager)).EndInit();
             this.stc_recordManager.ResumeLayout(false);
-            this.superTabControlPanel1.ResumeLayout(false);
-            this.tlp_parkingRecord.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.dgvx_parkingRecords)).EndInit();
-            this.tableLayoutPanel1.ResumeLayout(false);
-            this.tableLayoutPanel1.PerformLayout();
             this.superTabControlPanel2.ResumeLayout(false);
             this.tlp_orderRecords.ResumeLayout(false);
             ((System.ComponentModel.ISupportInitialize)(this.dgvx_orderRecords)).EndInit();
             this.tableLayoutPanel3.ResumeLayout(false);
             this.tableLayoutPanel3.PerformLayout();
+            this.superTabControlPanel1.ResumeLayout(false);
+            this.tlp_parkingRecord.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.dgvx_parkingRecords)).EndInit();
+            this.tableLayoutPanel1.ResumeLayout(false);
+            this.tableLayoutPanel1.PerformLayout();
             this.ResumeLayout(false);
 
         }

+ 18 - 18
PLCLinker/centralController/FormRecordsManager.resx

@@ -117,58 +117,58 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="parkingRecordsID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="userID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="numberPlate.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn5.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="parkingSpaceID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn6.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="realParkTime.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn7.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="realGetTime.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn8.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="receiptNum.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="dataGridViewTextBoxColumn9.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="parkingPrice.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="预约状态.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="paymentStatus.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="parkingRecordsID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="userID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="numberPlate.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="parkingSpaceID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn5.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="realParkTime.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn6.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="realGetTime.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn7.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="receiptNum.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn8.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="parkingPrice.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="dataGridViewTextBoxColumn9.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="paymentStatus.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+  <metadata name="预约状态.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
 </root>

+ 69 - 69
PLCLinker/centralController/FormSysConfig.Designer.cs

@@ -40,15 +40,15 @@ namespace centralController
             this.gp_PLCConf = new DevComponents.DotNetBar.Controls.GroupPanel();
             this.gp_AllInOneMachineConf = new DevComponents.DotNetBar.Controls.GroupPanel();
             this.gp_restConf = new DevComponents.DotNetBar.Controls.GroupPanel();
-            this.tb_garageID = new System.Windows.Forms.TextBox();
-            this.btnx_alterGarageId = new DevComponents.DotNetBar.ButtonX();
-            this.tb_defaultLic = new System.Windows.Forms.TextBox();
-            this.btnx_alterDefaultLic = new DevComponents.DotNetBar.ButtonX();
-            this.lbx_logAddress = new DevComponents.DotNetBar.LabelX();
-            this.lbx_advertAddress = new DevComponents.DotNetBar.LabelX();
-            this.btnx_alterLogAddress = new DevComponents.DotNetBar.ButtonX();
-            this.lbx_garageId = new DevComponents.DotNetBar.LabelX();
             this.lbx_defaultLic = new DevComponents.DotNetBar.LabelX();
+            this.lbx_garageId = new DevComponents.DotNetBar.LabelX();
+            this.btnx_alterLogAddress = new DevComponents.DotNetBar.ButtonX();
+            this.lbx_advertAddress = new DevComponents.DotNetBar.LabelX();
+            this.lbx_logAddress = new DevComponents.DotNetBar.LabelX();
+            this.btnx_alterDefaultLic = new DevComponents.DotNetBar.ButtonX();
+            this.tb_defaultLic = new System.Windows.Forms.TextBox();
+            this.btnx_alterGarageId = new DevComponents.DotNetBar.ButtonX();
+            this.tb_garageID = new System.Windows.Forms.TextBox();
             this.gp_numMachineConfig.SuspendLayout();
             this.gp_restConf.SuspendLayout();
             this.SuspendLayout();
@@ -319,54 +319,40 @@ namespace centralController
             this.gp_restConf.TabIndex = 3;
             this.gp_restConf.Text = "其他配置";
             // 
-            // tb_garageID
-            // 
-            this.tb_garageID.Location = new System.Drawing.Point(126, 23);
-            this.tb_garageID.Name = "tb_garageID";
-            this.tb_garageID.Size = new System.Drawing.Size(54, 21);
-            this.tb_garageID.TabIndex = 0;
+            // lbx_defaultLic
             // 
-            // btnx_alterGarageId
             // 
-            this.btnx_alterGarageId.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
-            this.btnx_alterGarageId.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
-            this.btnx_alterGarageId.Location = new System.Drawing.Point(233, 21);
-            this.btnx_alterGarageId.Name = "btnx_alterGarageId";
-            this.btnx_alterGarageId.Size = new System.Drawing.Size(75, 23);
-            this.btnx_alterGarageId.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
-            this.btnx_alterGarageId.TabIndex = 2;
-            this.btnx_alterGarageId.Text = "修改车库号";
             // 
-            // tb_defaultLic
             // 
-            this.tb_defaultLic.Location = new System.Drawing.Point(126, 70);
-            this.tb_defaultLic.Name = "tb_defaultLic";
-            this.tb_defaultLic.Size = new System.Drawing.Size(83, 21);
-            this.tb_defaultLic.TabIndex = 3;
+            this.lbx_defaultLic.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.lbx_defaultLic.Location = new System.Drawing.Point(14, 70);
+            this.lbx_defaultLic.Name = "lbx_defaultLic";
+            this.lbx_defaultLic.Size = new System.Drawing.Size(75, 23);
+            this.lbx_defaultLic.TabIndex = 10;
+            this.lbx_defaultLic.Text = "默认车牌:";
             // 
-            // btnx_alterDefaultLic
+            // lbx_garageId
             // 
-            this.btnx_alterDefaultLic.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
-            this.btnx_alterDefaultLic.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
-            this.btnx_alterDefaultLic.Location = new System.Drawing.Point(233, 70);
-            this.btnx_alterDefaultLic.Name = "btnx_alterDefaultLic";
-            this.btnx_alterDefaultLic.Size = new System.Drawing.Size(90, 23);
-            this.btnx_alterDefaultLic.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
-            this.btnx_alterDefaultLic.TabIndex = 5;
-            this.btnx_alterDefaultLic.Text = "修改默认车牌";
             // 
-            // lbx_logAddress
             // 
             // 
+            this.lbx_garageId.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.lbx_garageId.Location = new System.Drawing.Point(14, 23);
+            this.lbx_garageId.Name = "lbx_garageId";
+            this.lbx_garageId.Size = new System.Drawing.Size(75, 23);
+            this.lbx_garageId.TabIndex = 9;
+            this.lbx_garageId.Text = "车库号:";
             // 
+            // btnx_alterLogAddress
             // 
-            this.lbx_logAddress.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.lbx_logAddress.Location = new System.Drawing.Point(14, 109);
-            this.lbx_logAddress.Name = "lbx_logAddress";
-            this.lbx_logAddress.Size = new System.Drawing.Size(309, 41);
-            this.lbx_logAddress.TabIndex = 6;
-            this.lbx_logAddress.Text = "当前日志路径:";
-            this.lbx_logAddress.WordWrap = true;
+            this.btnx_alterLogAddress.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
+            this.btnx_alterLogAddress.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
+            this.btnx_alterLogAddress.Location = new System.Drawing.Point(126, 156);
+            this.btnx_alterLogAddress.Name = "btnx_alterLogAddress";
+            this.btnx_alterLogAddress.Size = new System.Drawing.Size(90, 33);
+            this.btnx_alterLogAddress.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
+            this.btnx_alterLogAddress.TabIndex = 8;
+            this.btnx_alterLogAddress.Text = "修改日志路径";
             // 
             // lbx_advertAddress
             // 
@@ -381,40 +367,54 @@ namespace centralController
             this.lbx_advertAddress.Text = "当前广告路径:";
             this.lbx_advertAddress.WordWrap = true;
             // 
-            // btnx_alterLogAddress
+            // lbx_logAddress
             // 
-            this.btnx_alterLogAddress.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
-            this.btnx_alterLogAddress.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
-            this.btnx_alterLogAddress.Location = new System.Drawing.Point(126, 156);
-            this.btnx_alterLogAddress.Name = "btnx_alterLogAddress";
-            this.btnx_alterLogAddress.Size = new System.Drawing.Size(90, 33);
-            this.btnx_alterLogAddress.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
-            this.btnx_alterLogAddress.TabIndex = 8;
-            this.btnx_alterLogAddress.Text = "修改日志路径";
             // 
-            // lbx_garageId
             // 
             // 
+            this.lbx_logAddress.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
+            this.lbx_logAddress.Location = new System.Drawing.Point(14, 109);
+            this.lbx_logAddress.Name = "lbx_logAddress";
+            this.lbx_logAddress.Size = new System.Drawing.Size(309, 41);
+            this.lbx_logAddress.TabIndex = 6;
+            this.lbx_logAddress.Text = "当前日志路径:";
+            this.lbx_logAddress.WordWrap = true;
             // 
+            // btnx_alterDefaultLic
             // 
-            this.lbx_garageId.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.lbx_garageId.Location = new System.Drawing.Point(14, 23);
-            this.lbx_garageId.Name = "lbx_garageId";
-            this.lbx_garageId.Size = new System.Drawing.Size(75, 23);
-            this.lbx_garageId.TabIndex = 9;
-            this.lbx_garageId.Text = "车库号:";
+            this.btnx_alterDefaultLic.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
+            this.btnx_alterDefaultLic.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
+            this.btnx_alterDefaultLic.Location = new System.Drawing.Point(233, 70);
+            this.btnx_alterDefaultLic.Name = "btnx_alterDefaultLic";
+            this.btnx_alterDefaultLic.Size = new System.Drawing.Size(90, 23);
+            this.btnx_alterDefaultLic.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
+            this.btnx_alterDefaultLic.TabIndex = 5;
+            this.btnx_alterDefaultLic.Text = "修改默认车牌";
             // 
-            // lbx_defaultLic
+            // tb_defaultLic
             // 
+            this.tb_defaultLic.Location = new System.Drawing.Point(126, 70);
+            this.tb_defaultLic.Name = "tb_defaultLic";
+            this.tb_defaultLic.Size = new System.Drawing.Size(83, 21);
+            this.tb_defaultLic.TabIndex = 3;
             // 
+            // btnx_alterGarageId
+            // 
+            this.btnx_alterGarageId.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;
+            this.btnx_alterGarageId.ColorTable = DevComponents.DotNetBar.eButtonColor.OrangeWithBackground;
+            this.btnx_alterGarageId.Location = new System.Drawing.Point(233, 21);
+            this.btnx_alterGarageId.Name = "btnx_alterGarageId";
+            this.btnx_alterGarageId.Size = new System.Drawing.Size(75, 23);
+            this.btnx_alterGarageId.Style = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
+            this.btnx_alterGarageId.TabIndex = 2;
+            this.btnx_alterGarageId.Text = "修改车库号";
             // 
+            // tb_garageID
             // 
-            this.lbx_defaultLic.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square;
-            this.lbx_defaultLic.Location = new System.Drawing.Point(14, 70);
-            this.lbx_defaultLic.Name = "lbx_defaultLic";
-            this.lbx_defaultLic.Size = new System.Drawing.Size(75, 23);
-            this.lbx_defaultLic.TabIndex = 10;
-            this.lbx_defaultLic.Text = "默认车牌:";
+            this.tb_garageID.Location = new System.Drawing.Point(126, 23);
+            this.tb_garageID.Name = "tb_garageID";
+            this.tb_garageID.Size = new System.Drawing.Size(54, 21);
+            this.tb_garageID.TabIndex = 0;
             // 
             // FormSysConfig
             // 
@@ -425,7 +425,7 @@ namespace centralController
             this.Controls.Add(this.gp_numMachineConfig);
             this.DoubleBuffered = true;
             this.Name = "FormSysConfig";
-            this.Text = "FormSysConfig";
+            this.Text = "系统配置";
             this.gp_numMachineConfig.ResumeLayout(false);
             this.gp_numMachineConfig.PerformLayout();
             this.gp_restConf.ResumeLayout(false);

+ 30 - 31
PLCLinker/centralController/Terminal/Terminal.cs

@@ -322,6 +322,21 @@ namespace Terminal
             Monitor.Monitor.PLC.WriteToPLC(tsFromTerminal, PLCDataType.terminal);
         }
         /// <summary>
+        /// 清除流程完成标记
+        /// </summary>
+        private static void ResetCompleteSignal()
+        {
+            MainBlockStru mbs = new MainBlockStru
+            {
+                centralHearbeat = (short)-1,
+                bookParkCmd = -1,
+                bookFetchCmd = -1,
+                processCompleted = (short)0,
+                licenseReceived = (short)-1
+            };
+            Monitor.Monitor.PLC.WriteToPLC(mbs, PLCDataType.central);
+        }
+        /// <summary>
         /// 更新PLC提供的特定车位状态
         /// </summary>
         /// <param name="state"></param>
@@ -507,15 +522,6 @@ namespace Terminal
                             catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "号牌" + license + "记录号牌异常\n" + e.StackTrace); }
                         }
                         Log.WriteLog(LogType.process, LogFile.INFO, "号牌" + license + "已记录");
-                        MainBlockStru mb = new MainBlockStru
-                        {
-                            centralHearbeat = (short)-1,
-                            bookParkCmd = -1,
-                            bookFetchCmd = -1,
-                            processCompleted = (short)0,
-                            licenseReceived = (short)-1
-                        };
-                        Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central);
                         //未获得号牌,告知PLC终止,告诉终端提示用户重新操作
                         if (license == "")
                         {
@@ -608,8 +614,7 @@ namespace Terminal
         /// </summary>
         private static void ParkCompleteSubProcess()
         {
-            Thread.Sleep(300);
-            Console.WriteLine(Monitor.Monitor.mainBlockInfo.parkingRunning+","+ Monitor.Monitor.mainBlockInfo.processCompleted);
+            //Console.WriteLine(Monitor.Monitor.mainBlockInfo.parkingRunning+","+ Monitor.Monitor.mainBlockInfo.processCompleted);
             int processAttrib = Monitor.Monitor.mainBlockInfo.parkingRunning;
             //int processCompleted = Monitor.Monitor.mainBlockInfo.processCompleted;
             int currentTerm = Monitor.Monitor.mainBlockInfo.terminalID;
@@ -623,7 +628,10 @@ namespace Terminal
                 {
                     if (Monitor.Monitor.mainBlockInfo.processStopped == 1)
                     {
-                        Console.WriteLine("中断");
+                        Log.WriteLog(LogType.process,LogFile.ERROR,"停车流程中断");
+                        Thread.Sleep(500);
+                        ClearTerminal(term.terminalID);
+                        ResetCompleteSignal();
                     }
                     return;
                 }
@@ -657,15 +665,6 @@ namespace Terminal
                         {
                             idLicMap.Remove(currentTerm);
                             ClearTerminal(term.terminalID);
-                            MainBlockStru mbs = new MainBlockStru
-                            {
-                                centralHearbeat = (short)-1,
-                                bookParkCmd = -1,
-                                bookFetchCmd = -1,
-                                processCompleted = (short)0,
-                                licenseReceived = (short)-1
-                            };
-                            Monitor.Monitor.PLC.WriteToPLC(mbs, PLCDataType.central);
                         }
                         catch { }
                         Monitor.Monitor.SetNotification("无车位或凭证号", parkMonitor.model.TextColor.Warning);
@@ -717,6 +716,9 @@ namespace Terminal
                     //}
                     //中控清除车牌、凭证号、号牌验证等信息
                     ClearTerminal(term.terminalID);
+                    //停车流程确保已清除中控块完成信号
+                    Thread.Sleep(500);
+                    ResetCompleteSignal();
                     try { idLicMap.Remove(currentTerm); }
                     catch { }
                     Monitor.Monitor.SetNotification(license + " 数据库已更新,停车流程结束", parkMonitor.model.TextColor.Info);
@@ -1146,15 +1148,6 @@ namespace Terminal
                 bool value = false;
                 if (termIndex != -1 && termCalcMap.Count >= termIndex && termCalcMap.TryGetValue(termIndex, out value) && !value && ts.cmd == 2 && receiptNum != 0)
                 {
-                    MainBlockStru mb = new MainBlockStru
-                    {
-                        centralHearbeat = (short)-1,
-                        bookParkCmd = -1,
-                        bookFetchCmd = -1,
-                        processCompleted = (short)0,
-                        licenseReceived = (short)-1
-                    };
-                    Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central);
                     //fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning;
                     Monitor.Monitor.SetNotification(termIndex + "号终端准备计算费用", parkMonitor.model.TextColor.Log);
                     termCalcMap[termIndex] = true;
@@ -1272,6 +1265,10 @@ namespace Terminal
                                 if (Monitor.Monitor.mainBlockInfo.processStopped == 1)
                                 {
                                     Log.WriteLog(LogType.process, LogFile.INFO, "检测到流程中断");
+                                    ClearTerminal(terminalInfo[termIndex].terminalID);
+                                    //停车流程确保已清除中控块完成信号
+                                    Thread.Sleep(500);
+                                    ResetCompleteSignal();
                                     break;
                                 }
                                 if (Monitor.Monitor.mainBlockInfo.processCompleted == 1)
@@ -1299,7 +1296,9 @@ namespace Terminal
                                     FetchInfo fi = null;
                                     UpdateAllParkingSpace(false);
                                     ClearTerminal(terminalInfo[termIndex].terminalID);
-
+                                    //停车流程确保已清除中控块完成信号
+                                    Thread.Sleep(500);
+                                    ResetCompleteSignal();
                                     if (fetchInfoMap.ContainsKey(terminalInfo[termIndex].terminalID))
                                     {
                                         fi = fetchInfoMap[terminalInfo[termIndex].terminalID];

+ 4 - 0
PLCLinker/centralController/centralController.csproj

@@ -33,6 +33,9 @@
     <WarningLevel>4</WarningLevel>
     <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>icon.ico</ApplicationIcon>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="broadcastDLL, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -358,6 +361,7 @@
     <None Include="resource\image\menu\sysExplain.png" />
     <None Include="resource\image\map\numMachine.png" />
     <None Include="resource\image\map\car.png" />
+    <Content Include="icon.ico" />
     <Content Include="sdk\broadcast\broadcastDLL.dll" />
     <Content Include="sdk\log4net\log4net.dll" />
     <Content Include="sdk\mysql\MySql.Data.dll" />

BIN
PLCLinker/centralController/icon.ico


BIN
PLCLinker/centralController/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache


BIN
PLCLinker/centralController/obj/Release/centralController.Properties.Resources.resources


+ 1 - 1
PLCLinker/centralController/obj/Release/centralController.csproj.CoreCompileInputs.cache

@@ -1 +1 @@
-06a8c02145b158084c7aeb48ba8e70c35f6aaaff
+e2e18498797396c0c4d793777c2850f188bce73b

BIN
PLCLinker/centralController/obj/Release/centralController.csproj.GenerateResource.Cache


+ 2 - 2
PLCLinker/centralController/serversettings.json

@@ -1,8 +1,8 @@
 {
 
   "ssl": "false",
-  "host": "192.168.0.106",
-  "garageID":"6",
+  "host": "192.168.10.125",
+  "garageID":"2",
   "port": "9000",
   "size": "1024"
 }

+ 451 - 0
PLCLinker/newPLCConnector/Form1.Designer.cs

@@ -0,0 +1,451 @@
+namespace PLCConnector
+{
+    partial class Form1
+    {
+        /// <summary>
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 窗体设计器生成的代码
+
+        /// <summary>
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.textBox2 = new System.Windows.Forms.TextBox();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.textBox4 = new System.Windows.Forms.TextBox();
+            this.button1 = new System.Windows.Forms.Button();
+            this.label3 = new System.Windows.Forms.Label();
+            this.textBox3 = new System.Windows.Forms.TextBox();
+            this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.textBox5 = new System.Windows.Forms.TextBox();
+            this.button2 = new System.Windows.Forms.Button();
+            this.textBox1 = new System.Windows.Forms.TextBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.textBox6 = new System.Windows.Forms.TextBox();
+            this.button3 = new System.Windows.Forms.Button();
+            this.textBox7 = new System.Windows.Forms.TextBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.groupBox4 = new System.Windows.Forms.GroupBox();
+            this.textBox8 = new System.Windows.Forms.TextBox();
+            this.button4 = new System.Windows.Forms.Button();
+            this.textBox9 = new System.Windows.Forms.TextBox();
+            this.label6 = new System.Windows.Forms.Label();
+            this.btn_clear = new System.Windows.Forms.Button();
+            this.button6 = new System.Windows.Forms.Button();
+            this.button5 = new System.Windows.Forms.Button();
+            this.button7 = new System.Windows.Forms.Button();
+            this.button8 = new System.Windows.Forms.Button();
+            this.button9 = new System.Windows.Forms.Button();
+            this.button10 = new System.Windows.Forms.Button();
+            this.button11 = new System.Windows.Forms.Button();
+            this.btn_input = new System.Windows.Forms.Button();
+            this.groupBox1.SuspendLayout();
+            this.groupBox2.SuspendLayout();
+            this.groupBox3.SuspendLayout();
+            this.groupBox4.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(6, 25);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(41, 12);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "数据块";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(6, 88);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(41, 12);
+            this.label2.TabIndex = 3;
+            this.label2.Text = "偏移量";
+            // 
+            // textBox2
+            // 
+            this.textBox2.Location = new System.Drawing.Point(6, 103);
+            this.textBox2.Name = "textBox2";
+            this.textBox2.Size = new System.Drawing.Size(121, 21);
+            this.textBox2.TabIndex = 2;
+            this.textBox2.Text = "2";
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.textBox4);
+            this.groupBox1.Controls.Add(this.button1);
+            this.groupBox1.Controls.Add(this.label3);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.textBox3);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.textBox2);
+            this.groupBox1.Location = new System.Drawing.Point(12, 12);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(155, 250);
+            this.groupBox1.TabIndex = 4;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "写入";
+            // 
+            // textBox4
+            // 
+            this.textBox4.Location = new System.Drawing.Point(8, 40);
+            this.textBox4.Name = "textBox4";
+            this.textBox4.Size = new System.Drawing.Size(121, 21);
+            this.textBox4.TabIndex = 7;
+            this.textBox4.Text = "中控";
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(23, 209);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 6;
+            this.button1.Text = "写入";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(6, 158);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(17, 12);
+            this.label3.TabIndex = 5;
+            this.label3.Text = "值";
+            // 
+            // textBox3
+            // 
+            this.textBox3.Location = new System.Drawing.Point(6, 173);
+            this.textBox3.Name = "textBox3";
+            this.textBox3.Size = new System.Drawing.Size(121, 21);
+            this.textBox3.TabIndex = 3;
+            this.textBox3.Text = "0";
+            // 
+            // groupBox2
+            // 
+            this.groupBox2.Controls.Add(this.textBox5);
+            this.groupBox2.Controls.Add(this.button2);
+            this.groupBox2.Controls.Add(this.textBox1);
+            this.groupBox2.Controls.Add(this.label4);
+            this.groupBox2.Location = new System.Drawing.Point(199, 12);
+            this.groupBox2.Name = "groupBox2";
+            this.groupBox2.Size = new System.Drawing.Size(171, 418);
+            this.groupBox2.TabIndex = 5;
+            this.groupBox2.TabStop = false;
+            this.groupBox2.Text = "读取";
+            // 
+            // textBox5
+            // 
+            this.textBox5.Location = new System.Drawing.Point(18, 40);
+            this.textBox5.Name = "textBox5";
+            this.textBox5.Size = new System.Drawing.Size(121, 21);
+            this.textBox5.TabIndex = 8;
+            this.textBox5.Text = "中控";
+            // 
+            // button2
+            // 
+            this.button2.Location = new System.Drawing.Point(46, 389);
+            this.button2.Name = "button2";
+            this.button2.Size = new System.Drawing.Size(75, 23);
+            this.button2.TabIndex = 7;
+            this.button2.Text = "读取";
+            this.button2.UseVisualStyleBackColor = true;
+            this.button2.Click += new System.EventHandler(this.button2_Click);
+            // 
+            // textBox1
+            // 
+            this.textBox1.Location = new System.Drawing.Point(18, 78);
+            this.textBox1.Multiline = true;
+            this.textBox1.Name = "textBox1";
+            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.textBox1.Size = new System.Drawing.Size(133, 305);
+            this.textBox1.TabIndex = 8;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(18, 25);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(41, 12);
+            this.label4.TabIndex = 6;
+            this.label4.Text = "数据块";
+            // 
+            // groupBox3
+            // 
+            this.groupBox3.Controls.Add(this.textBox6);
+            this.groupBox3.Controls.Add(this.button3);
+            this.groupBox3.Controls.Add(this.textBox7);
+            this.groupBox3.Controls.Add(this.label5);
+            this.groupBox3.Location = new System.Drawing.Point(397, 12);
+            this.groupBox3.Name = "groupBox3";
+            this.groupBox3.Size = new System.Drawing.Size(171, 418);
+            this.groupBox3.TabIndex = 6;
+            this.groupBox3.TabStop = false;
+            this.groupBox3.Text = "读取";
+            // 
+            // textBox6
+            // 
+            this.textBox6.Location = new System.Drawing.Point(18, 40);
+            this.textBox6.Name = "textBox6";
+            this.textBox6.Size = new System.Drawing.Size(121, 21);
+            this.textBox6.TabIndex = 8;
+            this.textBox6.Text = "终端1";
+            // 
+            // button3
+            // 
+            this.button3.Location = new System.Drawing.Point(46, 389);
+            this.button3.Name = "button3";
+            this.button3.Size = new System.Drawing.Size(75, 23);
+            this.button3.TabIndex = 7;
+            this.button3.Text = "读取";
+            this.button3.UseVisualStyleBackColor = true;
+            this.button3.Click += new System.EventHandler(this.button3_Click);
+            // 
+            // textBox7
+            // 
+            this.textBox7.Location = new System.Drawing.Point(18, 78);
+            this.textBox7.Multiline = true;
+            this.textBox7.Name = "textBox7";
+            this.textBox7.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.textBox7.Size = new System.Drawing.Size(133, 305);
+            this.textBox7.TabIndex = 8;
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(18, 25);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(41, 12);
+            this.label5.TabIndex = 6;
+            this.label5.Text = "数据块";
+            // 
+            // groupBox4
+            // 
+            this.groupBox4.Controls.Add(this.textBox8);
+            this.groupBox4.Controls.Add(this.button4);
+            this.groupBox4.Controls.Add(this.textBox9);
+            this.groupBox4.Controls.Add(this.label6);
+            this.groupBox4.Location = new System.Drawing.Point(587, 12);
+            this.groupBox4.Name = "groupBox4";
+            this.groupBox4.Size = new System.Drawing.Size(171, 418);
+            this.groupBox4.TabIndex = 9;
+            this.groupBox4.TabStop = false;
+            this.groupBox4.Text = "读取";
+            // 
+            // textBox8
+            // 
+            this.textBox8.Location = new System.Drawing.Point(18, 40);
+            this.textBox8.Name = "textBox8";
+            this.textBox8.Size = new System.Drawing.Size(121, 21);
+            this.textBox8.TabIndex = 8;
+            this.textBox8.Text = "车位1";
+            // 
+            // button4
+            // 
+            this.button4.Location = new System.Drawing.Point(46, 389);
+            this.button4.Name = "button4";
+            this.button4.Size = new System.Drawing.Size(75, 23);
+            this.button4.TabIndex = 7;
+            this.button4.Text = "读取";
+            this.button4.UseVisualStyleBackColor = true;
+            this.button4.Click += new System.EventHandler(this.button4_Click);
+            // 
+            // textBox9
+            // 
+            this.textBox9.Location = new System.Drawing.Point(18, 78);
+            this.textBox9.Multiline = true;
+            this.textBox9.Name = "textBox9";
+            this.textBox9.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.textBox9.Size = new System.Drawing.Size(133, 305);
+            this.textBox9.TabIndex = 8;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(18, 25);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(41, 12);
+            this.label6.TabIndex = 6;
+            this.label6.Text = "数据块";
+            // 
+            // btn_clear
+            // 
+            this.btn_clear.Location = new System.Drawing.Point(443, 459);
+            this.btn_clear.Name = "btn_clear";
+            this.btn_clear.Size = new System.Drawing.Size(75, 23);
+            this.btn_clear.TabIndex = 10;
+            this.btn_clear.Text = "终端1清零";
+            this.btn_clear.UseVisualStyleBackColor = true;
+            this.btn_clear.Click += new System.EventHandler(this.btn_clear_Click);
+            // 
+            // button6
+            // 
+            this.button6.Location = new System.Drawing.Point(35, 268);
+            this.button6.Name = "button6";
+            this.button6.Size = new System.Drawing.Size(75, 23);
+            this.button6.TabIndex = 11;
+            this.button6.Text = "自动刷新";
+            this.button6.UseVisualStyleBackColor = true;
+            this.button6.Click += new System.EventHandler(this.btn_refresh_Click);
+            // 
+            // button5
+            // 
+            this.button5.Location = new System.Drawing.Point(622, 433);
+            this.button5.Name = "button5";
+            this.button5.Size = new System.Drawing.Size(93, 23);
+            this.button5.TabIndex = 12;
+            this.button5.Text = "凭证写入车位";
+            this.button5.UseVisualStyleBackColor = true;
+            this.button5.Click += new System.EventHandler(this.button5_Click);
+            // 
+            // button7
+            // 
+            this.button7.Location = new System.Drawing.Point(443, 430);
+            this.button7.Name = "button7";
+            this.button7.Size = new System.Drawing.Size(75, 23);
+            this.button7.TabIndex = 13;
+            this.button7.Text = "启动地感";
+            this.button7.UseVisualStyleBackColor = true;
+            this.button7.Click += new System.EventHandler(this.button7_Click);
+            // 
+            // button8
+            // 
+            this.button8.Location = new System.Drawing.Point(245, 430);
+            this.button8.Name = "button8";
+            this.button8.Size = new System.Drawing.Size(75, 23);
+            this.button8.TabIndex = 14;
+            this.button8.Text = "启动号牌机";
+            this.button8.UseVisualStyleBackColor = true;
+            this.button8.Click += new System.EventHandler(this.button8_Click);
+            // 
+            // button9
+            // 
+            this.button9.Location = new System.Drawing.Point(245, 459);
+            this.button9.Name = "button9";
+            this.button9.Size = new System.Drawing.Size(75, 23);
+            this.button9.TabIndex = 15;
+            this.button9.Text = "停车完成";
+            this.button9.UseVisualStyleBackColor = true;
+            this.button9.Click += new System.EventHandler(this.button9_Click);
+            // 
+            // button10
+            // 
+            this.button10.Location = new System.Drawing.Point(12, 297);
+            this.button10.Name = "button10";
+            this.button10.Size = new System.Drawing.Size(120, 23);
+            this.button10.TabIndex = 16;
+            this.button10.Text = "切换中控停取模式";
+            this.button10.UseVisualStyleBackColor = true;
+            this.button10.Click += new System.EventHandler(this.button10_Click);
+            // 
+            // button11
+            // 
+            this.button11.Location = new System.Drawing.Point(12, 326);
+            this.button11.Name = "button11";
+            this.button11.Size = new System.Drawing.Size(120, 23);
+            this.button11.TabIndex = 17;
+            this.button11.Text = "切换终端1停取模式";
+            this.button11.UseVisualStyleBackColor = true;
+            this.button11.Click += new System.EventHandler(this.button11_Click);
+            // 
+            // btn_input
+            // 
+            this.btn_input.Location = new System.Drawing.Point(35, 372);
+            this.btn_input.Name = "btn_input";
+            this.btn_input.Size = new System.Drawing.Size(75, 23);
+            this.btn_input.TabIndex = 18;
+            this.btn_input.Text = "自动写入";
+            this.btn_input.UseVisualStyleBackColor = true;
+            this.btn_input.Click += new System.EventHandler(this.btn_input_Click);
+            // 
+            // Form1
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(803, 527);
+            this.Controls.Add(this.btn_input);
+            this.Controls.Add(this.button11);
+            this.Controls.Add(this.button10);
+            this.Controls.Add(this.button9);
+            this.Controls.Add(this.button8);
+            this.Controls.Add(this.button7);
+            this.Controls.Add(this.button5);
+            this.Controls.Add(this.button6);
+            this.Controls.Add(this.btn_clear);
+            this.Controls.Add(this.groupBox4);
+            this.Controls.Add(this.groupBox3);
+            this.Controls.Add(this.groupBox2);
+            this.Controls.Add(this.groupBox1);
+            this.Name = "Form1";
+            this.Text = "Form1";
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.groupBox2.ResumeLayout(false);
+            this.groupBox2.PerformLayout();
+            this.groupBox3.ResumeLayout(false);
+            this.groupBox3.PerformLayout();
+            this.groupBox4.ResumeLayout(false);
+            this.groupBox4.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox textBox2;
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.TextBox textBox3;
+        private System.Windows.Forms.GroupBox groupBox2;
+        private System.Windows.Forms.TextBox textBox1;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Button button2;
+        private System.Windows.Forms.TextBox textBox4;
+        private System.Windows.Forms.TextBox textBox5;
+        private System.Windows.Forms.GroupBox groupBox3;
+        private System.Windows.Forms.TextBox textBox6;
+        private System.Windows.Forms.Button button3;
+        private System.Windows.Forms.TextBox textBox7;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.GroupBox groupBox4;
+        private System.Windows.Forms.TextBox textBox8;
+        private System.Windows.Forms.Button button4;
+        private System.Windows.Forms.TextBox textBox9;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Button btn_clear;
+        private System.Windows.Forms.Button button6;
+        private System.Windows.Forms.Button button5;
+        private System.Windows.Forms.Button button7;
+        private System.Windows.Forms.Button button8;
+        private System.Windows.Forms.Button button9;
+        private System.Windows.Forms.Button button10;
+        private System.Windows.Forms.Button button11;
+        private System.Windows.Forms.Button btn_input;
+    }
+}
+

+ 554 - 0
PLCLinker/newPLCConnector/Form1.cs

@@ -0,0 +1,554 @@
+using parkMonitor.LOG;
+using PLCS7;
+using snap7Enc;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Configuration;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace PLCConnector
+{
+    public partial class Form1 : Form
+    {
+        PLCLinker pl;
+        bool flip = false;
+        Random rnd = new Random();
+        Stopwatch stopwatch = new Stopwatch();
+
+        public Form1()
+        {
+            InitializeComponent();
+            string ip = "";
+            short rack = 0;
+            short slot = 0;
+            string[] blockIds = new string[3];
+            try
+            {
+                ip = ConfigurationManager.AppSettings.Get("plcIpAddress");
+                rack = Int16.Parse(ConfigurationManager.AppSettings.Get("plcRack"));
+                slot = Int16.Parse(ConfigurationManager.AppSettings.Get("plcSlot"));
+                blockIds = (ConfigurationManager.AppSettings.Get("plcDatablockId")).Split(',');
+                pl = new PLCLinker(CpuType.S71500, ip, rack, slot, int.Parse(blockIds[0]), int.Parse(blockIds[1]), int.Parse(blockIds[2]), 6, 200);
+            }
+            catch (Exception e) { MessageBox.Show("配置文件异常"); }
+
+        }
+
+        public static void parkingSpaceDBTest(AbstractPLCLinker pl, Random rnd)
+        {
+            if (!pl.isConnected) { pl.PLCConnect(); }
+            else
+            {
+                //读车位表信息
+                List<object> psList = pl.ReadFromPLC(PLCDataType.parkingSpace, 1);
+                psList.AddRange(pl.ReadFromPLC(PLCDataType.parkingSpace, 2));
+                foreach (var ps in psList)
+                {
+                    Console.WriteLine(((ParkingSpaceStru)ps).ToString());
+                }
+                //写入车位状态信息
+                ParkingSpaceStru pss = new ParkingSpaceStru
+                {
+                    parkingSpace = (short)rnd.Next(1, 3),
+                    spaceStatus = (short)rnd.Next(0, 3)
+                };
+                pl.WriteToPLC(pss, PLCDataType.central);
+                Console.WriteLine("写入状态值");
+            }
+        }
+
+        public static void terminalDBTest(AbstractPLCLinker pl, Random rnd)
+        {
+            if (!pl.isConnected) { pl.PLCConnect(); }
+            else
+            {
+                //读终端块数据
+                List<object> tList = pl.ReadFromPLC(PLCDataType.terminal, 1);
+                foreach (var term in tList)
+                {
+                    Console.WriteLine(((TerminalStru)term).ToString());
+                }
+                //模拟中控写数据
+                TerminalStru tsCentral = new TerminalStru
+                {
+                    terminalID = 1,
+                    paymentStatus = (short)rnd.Next(100, 999),
+                    licVerification = -1,
+                    parkingFee = (short)rnd.Next(100, 999),
+                    userType = (short)rnd.Next(100, 999)
+                };
+                //模拟终端写数据
+                TerminalStru tsTerminal = new TerminalStru
+                {
+                    terminalID = 1,
+                    terminalStatus = (short)rnd.Next(100, 999),
+                    btnStatus = (short)rnd.Next(100, 999),
+                    licenseCodeA = (short)rnd.Next(100, 999),
+                    licenseCodeB = -1,
+                    licenseCodeC = (short)rnd.Next(100, 999),
+                    receiptNum = (short)rnd.Next(100, 999)
+                };
+                //pl.WriteToPLC(tsCentral, PLCDataType.central);
+                pl.WriteToPLC(tsTerminal, PLCDataType.terminal);
+            }
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            PLCDataType type = PLCDataType.parkingSpace;
+            int offset = 0;
+            int value = 0;
+            try
+            {
+                offset = Int32.Parse(textBox2.Text);
+                value = Int32.Parse(textBox3.Text);
+            }
+            catch { MessageBox.Show("异常"); return; }
+            switch (textBox4.Text)
+            {
+                case "中控":
+                    type = PLCDataType.central;
+                    break;
+                case "终端1":
+                    type = PLCDataType.terminal;
+                    break;
+                case "终端2":
+                    type = PLCDataType.terminal;
+                    offset += 42;
+                    break;
+                case "终端3":
+                    type = PLCDataType.terminal;
+                    offset += 42 * 2;
+                    break;
+                case "车位1":
+                    type = PLCDataType.parkingSpace;
+                    break;
+                case "车位2":
+                    type = PLCDataType.parkingSpace;
+                    offset += 36;
+                    break;
+            }
+            if (value < 32768)
+            {
+                pl.WriteAccordingToOffset(type, offset, (short)value);
+            }
+            else
+            {
+                pl.WriteAccordingToOffset(type, offset, value);
+            }
+        }
+
+        private void button2_Click(object sender, EventArgs e)
+        {
+            //PLCDataType type = PLCDataType.parkingSpace;
+            //int id = -1;
+            //switch ((string)textBox5.Text)
+            //{
+            //    case "中控":
+            //        type = PLCDataType.central; id = 0;
+            //        break;
+            //    case "终端1":
+            //        type = PLCDataType.terminal; id = 1;
+            //        break;
+            //    case "终端2":
+            //        type = PLCDataType.terminal; id = 2;
+            //        break;
+            //    case "终端3":
+            //        type = PLCDataType.terminal; id = 3;
+            //        break;
+            //    case "车位1":
+            //        type = PLCDataType.parkingSpace; id = 4;
+            //        break;
+            //    case "车位2":
+            //        type = PLCDataType.parkingSpace; id = 5;
+            //        break;
+            //}
+            //string result = "";
+            //try
+            //{
+            //    if (id >= 4)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id - 3);
+            //        result = ((ParkingSpaceStru)list[0]).ToString();
+            //    }
+            //    else if (id > 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((TerminalStru)list[0]).ToString();
+            //        if (((TerminalStru)list[0]).terminalID == 0 || ((TerminalStru)list[0]).terminalStatus == 0)
+            //        {
+            //            Log.WriteLog(LogType.process, "读到终端0数据\n" + result + "\n*********************************");
+            //        }
+            //    }
+            //    else if (id == 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((MainBlockStru)list[0]).ToString();
+            //    }
+            //}
+            //catch { Console.WriteLine("异常"); Log.WriteLog(LogType.process, "与plc连接断开\n*********************************"); return; }
+            //textBox1.Text = result.Replace(",", "\r\n");
+            display(textBox5.Text, textBox1);
+        }
+
+        private void button3_Click(object sender, EventArgs e)
+        {
+            //PLCDataType type = PLCDataType.parkingSpace;
+            //int id = -1;
+            //switch ((string)textBox6.Text)
+            //{
+            //    case "中控":
+            //        type = PLCDataType.central; id = 0;
+            //        break;
+            //    case "终端1":
+            //        type = PLCDataType.terminal; id = 1;
+            //        break;
+            //    case "终端2":
+            //        type = PLCDataType.terminal; id = 2;
+            //        break;
+            //    case "终端3":
+            //        type = PLCDataType.terminal; id = 3;
+            //        break;
+            //    case "车位1":
+            //        type = PLCDataType.parkingSpace; id = 4;
+            //        break;
+            //    case "车位2":
+            //        type = PLCDataType.parkingSpace; id = 5;
+            //        break;
+            //}
+            //string result = "";
+            //try
+            //{
+            //    if (id >= 4)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id - 3);
+            //        Console.WriteLine(list.Count());
+            //        result = ((ParkingSpaceStru)list[0]).ToString();
+            //    }
+            //    else if (id > 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((TerminalStru)list[0]).ToString();
+            //        if(((TerminalStru)list[0]).terminalID!=id)
+            //        {
+            //            Log.WriteLog(LogType.process, "读到终端数据异常\n"+result+"\n*********************************");
+            //        }
+            //    }
+            //    else if (id == 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((MainBlockStru)list[0]).ToString();
+            //    }
+            //}
+            //catch { Console.WriteLine("异常"); Log.WriteLog(LogType.process, "与plc连接断开\n*********************************"); return; }
+            //textBox7.Text = result.Replace(",", "\r\n");
+            display(textBox6.Text, textBox7);
+        }
+
+        private void button4_Click(object sender, EventArgs e)
+        {
+            //PLCDataType type = PLCDataType.parkingSpace;
+            //int id = -1;
+            //switch ((string)textBox8.Text)
+            //{
+            //    case "中控":
+            //        type = PLCDataType.central; id = 0;
+            //        break;
+            //    case "终端1":
+            //        type = PLCDataType.terminal; id = 1;
+            //        break;
+            //    case "终端2":
+            //        type = PLCDataType.terminal; id = 2;
+            //        break;
+            //    case "终端3":
+            //        type = PLCDataType.terminal; id = 3;
+            //        break;
+            //    case "车位1":
+            //        type = PLCDataType.parkingSpace; id = 4;
+            //        break;
+            //    case "车位2":
+            //        type = PLCDataType.parkingSpace; id = 5;
+            //        break;
+            //}
+            //string result = "";
+            //try
+            //{
+            //    if (id >= 4)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id - 3);
+            //        result = ((ParkingSpaceStru)list[0]).ToString();
+            //    }
+            //    else if (id > 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((TerminalStru)list[0]).ToString();
+            //        if (((TerminalStru)list[0]).terminalID == 0 || ((TerminalStru)list[0]).terminalStatus == 0)
+            //        {
+            //            Log.WriteLog(LogType.process, "读到终端0数据\n" + result + "\n*********************************");
+            //        }
+            //    }
+            //    else if (id == 0)
+            //    {
+            //        List<object> list = pl.ReadFromPLC(type, id);
+            //        result = ((MainBlockStru)list[0]).ToString();
+            //    }
+            //}
+            //catch { Console.WriteLine("异常"); Log.WriteLog(LogType.process, "与plc连接断开\n*********************************"); return; }
+            //textBox9.Text = result.Replace(",", "\r\n");
+            display(textBox8.Text, textBox9);
+        }
+
+        private void display(string target, TextBox tb)
+        {
+            //stopwatch.Restart();
+            string result = "";
+            PLCDataType type = PLCDataType.parkingSpace;
+            int id = -1;
+            int index = 0;
+            try
+            {
+                if (target.Length > 2)
+                    index = int.Parse(target.Substring(2, target.Length - 2));
+            }
+            catch (Exception ex) { index = 0; Console.WriteLine("aaaaa"); }
+            try
+            {
+                string block = target.Substring(0, 2);
+                switch (block)
+                {
+                    case "中控":
+                        type = PLCDataType.central; id = 1001;
+                        break;
+                    case "终端":
+                        type = PLCDataType.terminal;
+                        id = 2000 + index;
+                        break;
+                    case "车位":
+                        type = PLCDataType.parkingSpace;
+                        id = 3000 + index;
+                        break;
+                }
+            }
+            catch { tb.Text = result.Replace(",", "\r\n"); return; }
+            try
+            {
+                if (id == 1001)
+                {
+                    List<object> list = pl.ReadFromPLC(type, 0);
+                    result = ((MainBlockStru)list[0]).ToString();
+                }
+                else if (id >= 3000)
+                {
+                    List<object> list = pl.ReadFromPLC(type, id - 3000);
+                    result = ((ParkingSpaceStru)list[0]).ToString();
+                }
+                else if (id >= 2000)
+                {
+                    List<object> list = pl.ReadFromPLC(type, id - 2000);
+                    result = ((TerminalStru)list[0]).ToString();
+                    if (((TerminalStru)list[0]).terminalID == 0 || ((TerminalStru)list[0]).terminalStatus == 0)
+                    {
+                        Log.WriteLog(LogType.process, "读到终端0数据\n" + result + "\n*********************************");
+                    }
+                }
+                else
+                {
+                    Console.WriteLine("无法识别输入"); return;
+                }
+            }
+            catch { Console.WriteLine("异常"); Log.WriteLog(LogType.process, "与plc连接断开\n*********************************"); return; }
+            tb.Text = result.Replace(",", "\r\n");
+            //stopwatch.Stop();
+            //Console.WriteLine(id + "---" + stopwatch.ElapsedMilliseconds / 1000.0f);
+        }
+
+        private void btn_refresh_Click(object sender, EventArgs e)
+        {
+            System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
+            timer1.Interval = 400;
+            timer1.Tick += new EventHandler(button2_Click);
+            timer1.Start();
+            System.Windows.Forms.Timer timer2 = new System.Windows.Forms.Timer();
+            timer2.Interval = 400;
+            timer2.Tick += new EventHandler(button3_Click);
+            timer2.Start();
+            System.Windows.Forms.Timer timer3 = new System.Windows.Forms.Timer();
+            timer3.Interval = 400;
+            timer3.Tick += new EventHandler(button4_Click);
+            timer3.Start();
+        }
+
+        private void btn_clear_Click(object sender, EventArgs e)
+        {
+            TerminalStru tsFromCentral = new TerminalStru
+            {
+                terminalID = 1,
+                parkingFee = (short)32767,
+                paymentStatus = (short)0,
+                licVerification = (short)0,
+                userType = (short)0,
+            };
+            TerminalStru tsFromTerminal = new TerminalStru
+            {
+                terminalID = 1,
+                btnStatus = -1,
+                cmd = (short)0,
+                receiptNum = (short)0,
+            };
+            pl.WriteToPLC(tsFromCentral, PLCDataType.central);
+            pl.WriteToPLC(tsFromTerminal, PLCDataType.terminal);
+        }
+        /// <summary>
+        /// 凭证号写入车位
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button5_Click(object sender, EventArgs e)
+        {
+            List<object> list = pl.ReadFromPLC(PLCDataType.terminal, 1);
+            int receipt = ((TerminalStru)list[0]).receiptNum;
+            pl.WriteAccordingToOffset(PLCDataType.parkingSpace, 14, receipt);
+        }
+        /// <summary>
+        /// 启动地感
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button7_Click(object sender, EventArgs e)
+        {
+            List<object> list = pl.ReadFromPLC(PLCDataType.terminal, 1);
+            short ground = ((TerminalStru)list[0]).groundStatus;
+            if (ground == (short)1)
+            {
+                pl.WriteAccordingToOffset(PLCDataType.terminal, 40, (short)0);
+            }
+            else
+            {
+                pl.WriteAccordingToOffset(PLCDataType.terminal, 40, (short)1);
+            }
+        }
+        /// <summary>
+        /// 启动号牌机
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button8_Click(object sender, EventArgs e)
+        {
+            pl.WriteAccordingToOffset(PLCDataType.central, 2, (short)1);
+        }
+        /// <summary>
+        /// 清空中控db
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button9_Click(object sender, EventArgs e)
+        {
+            List<object> list = pl.ReadFromPLC(PLCDataType.central, 0);
+            short complete = ((MainBlockStru)list[0]).processCompleted;
+            if (complete == (short)0)
+            {
+                pl.WriteAccordingToOffset(PLCDataType.central, 2, (short)0);
+                pl.WriteAccordingToOffset(PLCDataType.central, 16, (short)1);
+                pl.WriteAccordingToOffset(PLCDataType.central, 52, (short)0);
+
+            }
+            else
+            {
+                pl.WriteAccordingToOffset(PLCDataType.central, 2, (short)0);
+                pl.WriteAccordingToOffset(PLCDataType.central, 16, (short)0);
+                pl.WriteAccordingToOffset(PLCDataType.central, 52, (short)0);
+
+            }
+        }
+        /// <summary>
+        /// 切换中控停取模式
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button10_Click(object sender, EventArgs e)
+        {
+            List<object> list = pl.ReadFromPLC(PLCDataType.central, 0);
+            short park = ((MainBlockStru)list[0]).parkingRunning;
+            if (park == (short)0)
+            {
+                pl.WriteAccordingToOffset(PLCDataType.central, 12, (short)1);
+                pl.WriteAccordingToOffset(PLCDataType.central, 14, (short)0);
+            }
+            else
+            {
+                pl.WriteAccordingToOffset(PLCDataType.central, 12, (short)0);
+                pl.WriteAccordingToOffset(PLCDataType.central, 14, (short)1);
+            }
+        }
+        /// <summary>
+        /// 切换终端停取模式
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void button11_Click(object sender, EventArgs e)
+        {
+            List<object> list = pl.ReadFromPLC(PLCDataType.terminal, 1);
+            short termStatus = ((TerminalStru)list[0]).terminalStatus;
+            if (termStatus == (short)1)
+            {
+                pl.WriteAccordingToOffset(PLCDataType.terminal, 2, (short)2);
+            }
+            else
+            {
+                pl.WriteAccordingToOffset(PLCDataType.terminal, 2, (short)1);
+            }
+        }
+
+        private void autoWrite(object sender, EventArgs e)
+        {
+            //启动心跳进程
+            TerminalStru ts = new TerminalStru
+            {
+                terminalID = (short)1,
+                paymentStatus = 1,
+                parkingFee = 2,
+                userType = 3,
+                licVerification = (short)4
+            };
+            TerminalStru ts2 = new TerminalStru
+            {
+                terminalID = (short)1,
+            };
+            if (pl.isConnected)
+            {
+                flip = !flip;
+                MainBlockStru mbs = new MainBlockStru();
+                List<object> list = pl.ReadFromPLC(PLCDataType.central, 0);
+                if (list.Count != 0)
+                {
+                    mbs = (MainBlockStru)list[0];
+                    mbs.centralHearbeat = (short)rnd.Next(100, 999);
+                    mbs.licenseReceived = (short)-1;
+                    mbs.bookParkCmd = (short)-1;
+                    mbs.bookFetchCmd = (short)-1;
+                    pl.WriteToPLC(mbs, PLCDataType.central);
+                }
+                if (flip)
+                    pl.WriteToPLC(ts, PLCDataType.central);
+                else
+                    pl.WriteToPLC(ts2, PLCDataType.central);
+            }
+        }
+
+        private void btn_input_Click(object sender, EventArgs e)
+        {
+            System.Windows.Forms.Timer timer4 = new System.Windows.Forms.Timer();
+            timer4.Interval = 350;
+            timer4.Tick += new EventHandler(autoWrite);
+            timer4.Start();
+        }
+    }
+}

+ 120 - 0
PLCLinker/newPLCConnector/Form1.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 194 - 0
PLCLinker/newPLCConnector/LOG/LogManager.cs

@@ -0,0 +1,194 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using System.Configuration;
+
+namespace parkMonitor.LOG
+{
+    /// <summary>
+    /// 日志管理
+    /// </summary>
+    public class LogManager
+    {
+        public static string logAddressStr = "LogAddress";
+        public static string logAddress;
+        DateTime time;                                        //文件创建时间
+        private string logFileExtName = "log";     //日志文件扩展名
+        private Encoding logFileEncoding = Encoding.UTF8;   //日志文件编码格式
+        private string logFileName = string.Empty;  //日志文件名
+        private string logPath = "";            //日志文件路径
+        private bool writeLogTime = true;     //log文件是否写时间
+        private bool writeStatus = false;        //是否写入标志位
+        private static object obj = new object();
+        /// <summary>
+        /// 配置文件初始化
+        /// </summary>
+        public static void Init()
+        {
+            try
+            {
+                logAddress = ConfigurationManager.AppSettings[logAddressStr];
+            }
+            catch
+            {
+                Console.WriteLine("配置文件有误");
+            }
+        }
+        /// <summary>
+        /// 日志文件路径
+        /// </summary>
+        public string CreateLogPath()
+        {
+            if (logPath == null || logPath == string.Empty || time.ToString("yyyy-MM-dd") != System.DateTime.Now.ToString("yyyy-MM-dd"))
+            {
+                try
+                {
+                    time = System.DateTime.Now;
+                    logPath = System.IO.Path.Combine(logAddress, time.ToString("yyyy-MM-dd"));
+                }
+                catch
+                {
+                    Console.WriteLine("路径合成失败");
+                }
+            }
+            if (!logPath.EndsWith(@"\"))
+            {
+                logPath += @"\";
+            }
+            if (!Directory.Exists(logPath))
+            {
+                try
+                {
+                    Directory.CreateDirectory(logPath);
+                }
+                catch
+                {
+                    Console.WriteLine("创建文件路径失败");
+                }
+            }
+            return logPath;
+        }
+        /// <summary>
+        /// 写日志
+        /// </summary>
+        public void WriteLog(LogType logType, string logFile, string msg)
+        {
+            CreateLogPath();
+            lock (obj)
+            {
+                try
+                {
+                    //创建log文件
+                    logFileName = string.Format("{0}{1}.{2}", logPath, logType, this.logFileExtName);
+                    using (StreamWriter sw = new StreamWriter(logFileName, true, logFileEncoding))
+                    {
+                        //是否写时间
+                        if (logType == LogType.database)
+                        {
+                            writeLogTime = false;
+                        }
+                        else
+                        {
+                            writeLogTime = true;
+                        }
+                        ////sql类型
+                        //if (logType == LogType.DATABASE)
+                        //{
+                        //    writeStatus = true;
+                        //}
+                        //else
+                        //{
+                        //    writeStatus = false;
+                        //}
+                        if (writeLogTime)
+                        {
+                            sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:") + logFile + ":" + msg);
+                        }
+                        else
+                        {
+                            sw.WriteLine(logFile + ":" + msg);
+
+                        }
+                    }
+                }
+                catch { }
+            }
+        }
+        /// <summary>
+        /// log类型不定
+        /// </summary>
+        /// <param name="logType"></param>
+        /// <param name="logFile"></param>
+        /// <param name="msg"></param>
+        public void WriteLog(LogType logType, LogFile logFile, string msg)
+        {
+            this.WriteLog(logType, logFile.ToString(), msg);
+        }
+        /// <summary>
+        /// log类型为null
+        /// </summary>
+        /// <param name="logType"></param>
+        /// <param name="msg"></param>
+        public void WriteLog(LogType logType, string msg)
+        {
+            this.WriteLog(logType, string.Empty, msg);
+        }
+        /// <summary>
+        /// 读日志文件
+        /// </summary>
+        /// <param name="sqlStatus"></param>
+        /// <param name="sqlMsg"></param>
+        public void ReadLog(out string sqlStatus, out string sqlMsg, out int count)
+        {
+            sqlStatus = null;
+            sqlMsg = null;
+            count = 0;
+            string date = System.DateTime.Now.ToString("yyyy-MM-dd");
+            string filePath = logAddress + "\\\\" + date + "\\\\" + "DATABASE.log";
+            try
+            {
+                List<string> logLines = null;
+                if (File.Exists(filePath))
+                {
+                    logLines = new List<string>(File.ReadAllLines(filePath));
+                }
+                if (logLines != null)
+                {
+                    count = logLines.Count;
+                    string logLine = logLines[0];
+                    sqlStatus = logLine.Substring(0, 1);
+                    sqlMsg = logLine.Substring(2, logLine.Length - 2);
+                    logLines.RemoveAt(0);
+                    File.WriteAllLines(filePath, logLines.ToArray());
+                }
+            }
+            catch (Exception e) { Console.WriteLine(e.Message); }
+        }
+
+
+
+    }
+    /// <summary>
+    /// log类型
+    /// </summary>
+    public enum LogFile
+    {
+        LOG,
+        RESET,
+        ERROR,
+        WARNING,
+        INFO,
+        ERROR_NUMBERPLATE
+    }
+    /// <summary>
+    /// log文件类型
+    /// </summary>
+    public enum LogType
+    {
+        database,
+        process
+    }
+}

+ 25 - 0
PLCLinker/newPLCConnector/LOG/LogTest.cs

@@ -0,0 +1,25 @@
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using System.Threading.Tasks;
+
+//namespace parkMonitor.LOG
+//{
+//    //日志测试用例
+//    class LogTest
+//    {
+//        public void TestMethod()
+//        {
+//            //三种方式写入文件
+//            //第一种:WriteLog( string msg) 默认是INFO类型
+//            //第二种:WriteLog(string logFile,string msg) log类型和信息
+//            //第三种:WriteLog(LogFile logFile,string msg) 枚举的log类型以及相应信息
+//            LogFile logFile = LogFile.ERROR;
+//            string msg = "2";
+//            Log.WriteLog("",logFile, msg);
+//            Log.WriteLog("",msg);
+//            Log.WriteLog("WARNING", "22");
+//        }
+//    }
+//}

+ 87 - 0
PLCLinker/newPLCConnector/LOG/log.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace parkMonitor.LOG
+{
+    public static class Log
+    {
+        private static LogManager logManager;
+        static Log()
+        {
+            LogManager.Init();
+            logManager = new LogManager();
+        }
+        /// <summary>
+        /// 写文件类型
+        /// </summary>
+        /// <param name="logType"></param>
+        /// <param name="logFile"></param>
+        /// <param name="msg"></param>
+        public static void WriteLog(LogType logType, LogFile logFile, string msg)
+        {
+            try
+            {
+                logManager.WriteLog(logType, logFile, msg);
+            }
+            catch
+            {
+
+            }
+        }
+        /// <summary>
+        /// 文件类型为null
+        /// </summary>
+        /// <param name="logType"></param>
+        /// <param name="msg"></param>
+        public static void WriteLog(LogType logType, string msg)
+        {
+            try
+            {
+                logManager.WriteLog(logType, string.Empty, msg);
+            }
+            catch
+            {
+
+            }
+        }
+        /// <summary>
+        /// 数据库异常的标志位
+        /// 0表示update,1表示insert
+        /// </summary>
+        /// <param name="logType"></param>
+        /// <param name="status"></param>
+        /// <param name="msg"></param>
+        public static void WriteLog(LogType logType, string status, string msg)
+        {
+            try
+            {
+                logManager.WriteLog(logType, status, msg);
+            }
+            catch
+            {
+
+            }
+        }
+        /// <summary>
+        /// 读日志文件
+        /// </summary>
+        /// <param name="sqlStatus"></param>
+        /// <param name="sqlMsg"></param>
+        /// <param name="count"></param>      
+        public static void ReadLog(out string sqlStatus, out string sqlMsg,out int count)
+        {
+            sqlStatus = null;
+            sqlMsg = null;
+            count = 0;
+            try
+            {
+                logManager.ReadLog(out sqlStatus,out sqlMsg,out count);
+            }
+            catch { }
+        }
+
+    }
+}

BIN
PLCLinker/newPLCConnector/PLC/PLCS7.dll


+ 439 - 0
PLCLinker/newPLCConnector/PLC/PLCS7.xml

@@ -0,0 +1,439 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>PLCS7</name>
+    </assembly>
+    <members>
+        <member name="F:PLCS7.AbstractPLCLinker.isConnected">
+            <summary>
+            PLC 连接状态flag
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.cpu">
+            <summary>
+            plc中cpu类型
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.ip">
+            <summary>
+            PLC的IP地址
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.rack">
+            <summary>
+            PLC的端口号
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.slot">
+            <summary>
+            工作站号
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.terminalDB">
+            <summary>
+            终端DB块iD
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.centralDB">
+            <summary>
+            中心DB块iD
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.parkingSpaceDB">
+            <summary>
+            车位DB块ID
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.terminalCount">
+            <summary>
+            终端个数
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.parkingSpaceCount">
+            <summary>
+            停车位个数
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.plc">
+            <summary>
+            PLC S7连接对象
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.writingBlockingCollection">
+            <summary>
+            用于将写PLC指令排队的阻塞队列
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.writeThread">
+            <summary>
+            写线程,控制PLC写入频率
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.closed">
+            <summary>
+            系统关闭
+            </summary>
+        </member>
+        <member name="F:PLCS7.AbstractPLCLinker.readWriteLock">
+            <summary>
+            读写锁
+            </summary>
+        </member>
+        <member name="M:PLCS7.AbstractPLCLinker.PLCConnect">
+            <summary>
+            连接
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.AbstractPLCLinker.PLCDisconnect">
+            <summary>
+            断开连接
+            </summary>
+        </member>
+        <member name="M:PLCS7.AbstractPLCLinker.ReadFromPLC(PLCS7.PLCDataType,System.Int32)">
+            <summary>
+            读PLC
+            </summary>
+            <param name="whichToRead"></param>
+            <param name="index"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.AbstractPLCLinker.WriteToPLC(System.Object,PLCS7.PLCDataType)">
+            <summary>
+            写PLC
+            </summary>
+            <param name="abstractPLCMsg"></param>
+            <param name="whoami"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.#ctor(snap7Enc.CpuType,System.String,System.Int16,System.Int16,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)">
+            <summary>
+            PLCLinker构造函数
+            </summary>
+            <param name="cpu"></param>
+            <param name="ip"></param>
+            <param name="rack"></param>
+            <param name="slot"></param>
+            <param name="terminalDB"></param>
+            <param name="centralDB"></param>
+            <param name="parkingSpaceDB"></param>
+        </member>
+        <member name="M:PLCS7.PLCLinker.ReadMultipleBytes(System.Int32,System.Int32,System.Int32)">
+            <summary>
+            读取指定数据块中多个字节
+            </summary>
+            <param name="db"></param>
+            <param name="length"></param>
+            <param name="startAddr"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.WriteMultipleBytes(System.Int32,System.Collections.Generic.List{System.Byte},System.Int32)">
+            <summary>
+            写入指定数据块中多个字节
+            </summary>
+            <param name="db"></param>
+            <param name="bytesToWrite"></param>
+            <param name="startAddr"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.ReadStruFromPLC(System.Object,System.Int32,System.Int32)">
+            <summary>
+            从PLC中读取结构体
+            </summary>
+            <param name="obj"></param>
+            <param name="db"></param>
+            <param name="startAddr"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.WriteStruToPLC(System.Object,System.Int32,System.Int32)">
+            <summary>
+            向PLC中写入结构体
+            </summary>
+            <param name="obj"></param>
+            <param name="db"></param>
+            <param name="startAddr"></param>
+        </member>
+        <member name="M:PLCS7.PLCLinker.WriteAccordingly">
+            <summary>
+            从阻塞队列获取需写入PLC数据并写入PLC,时间间隔在线程中控制
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.ReadFromPLC(PLCS7.PLCDataType,System.Int32)">
+            <summary>
+            读取PLC数据块
+            </summary>
+            <param name="whichToRead"></param>
+            <param name="index"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.WriteToPLC(System.Object,PLCS7.PLCDataType)">
+            <summary>
+            写入PLC,其中可写入但不需写入字段请赋值为-1
+            </summary>
+            <param name="abstractPLCMsg"></param>
+            <param name="whoami"></param>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.PLCConnect">
+            <summary>
+            连接PLC
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:PLCS7.PLCLinker.PLCDisconnect">
+            <summary>
+            关闭PLC连接
+            </summary>
+        </member>
+        <member name="M:PLCS7.PLCLinker.WriteAccordingToOffset(PLCS7.PLCDataType,System.Int32,System.Object)">
+            <summary>
+            根据地址偏移量写入PLC
+            </summary>
+            <param name="whichToWrite"></param>
+            <param name="offset"></param>
+            <param name="value"></param>
+            <returns></returns>
+        </member>
+        <member name="T:PLCS7.TerminalStru">
+            <summary>
+            终端数据块结构体
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.terminalID">
+            <summary>
+            终端ID号
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.terminalStatus">
+            <summary>
+            终端状态,0暂停,1停车,2取车
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.btnStatus">
+            <summary>
+            按钮状态,0缺省,1非注册,2注册,3预约
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.cmd">
+            <summary>
+            停取指令,0缺省,1停车,2取车
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.licenseCodeA">
+            <summary>
+            注册用户UserID
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.licenseCodeB">
+            <summary>
+            注册用户号牌地域标记
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.licenseCodeC">
+            <summary>
+            注册用户号牌后半部分A
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.licenseCodeD">
+            <summary>
+            注册用户号牌后半部分B
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.receiptNum">
+            <summary>
+            凭证号
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.paymentStatus">
+            <summary>
+            支付状态,0-1失败-2成功-3管理员放行
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.licVerification">
+            <summary>
+            1-成功,2-号牌比对不成功
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.parkingFee">
+            <summary>
+            停车费用,0-99999
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.userType">
+            <summary>
+            用户类型,0-1普通-2月卡-3季卡-4年卡VIP
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.coordX">
+            <summary>
+            X坐标
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.coordY">
+            <summary>
+            Y坐标
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.groundStatus">
+            <summary>
+            地感信号
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.numMachineLaunch">
+            <summary>
+            启动对应号牌机
+            </summary>
+        </member>
+        <member name="F:PLCS7.TerminalStru.termHeartbeat">
+            <summary>
+            终端心跳
+            </summary>
+        </member>
+        <member name="T:PLCS7.MainBlockStru">
+            <summary>
+            中控与PLC交互使用数据块的结构体
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.terminalID">
+            <summary>
+            终端ID号
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.numMachineLaunch">
+            <summary>
+            号牌机启动指令
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.sweepLaserLaunch">
+            <summary>
+            摆扫启动指令
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.wheelbaseLaserLaunch">
+            <summary>
+            轮距启动指令
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.stop">
+            <summary>
+            急停
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.ready">
+            <summary>
+            就绪
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.parkingRunning">
+            <summary>
+            停车运行
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.fetchingRunning">
+            <summary>
+            取车运行
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.processCompleted">
+            <summary>
+            流程完成
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.processStopped">
+            <summary>
+            流程中断
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.sweepLaserStatus">
+            <summary>
+            摆扫激光状态
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.wheelbaseLaserStatus">
+            <summary>
+            轮距雷达状态
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.licenseReceived">
+            <summary>
+            号牌机获取
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.localAutoMode">
+            <summary>
+            本地自动模式
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.remoteMode">
+            <summary>
+            云端模式
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.localManualMode">
+            <summary>
+            本地手动模式
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.centralHearbeat">
+            <summary>
+            中控心跳
+            </summary>
+        </member>
+        <member name="F:PLCS7.MainBlockStru.reserveTotalSpace">
+            <summary>
+            预约车位总数
+            </summary>
+        </member>
+        <member name="T:PLCS7.ParkingSpaceStru">
+            <summary>
+            车位单元结构体
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.parkingSpace">
+            <summary>
+            车位编号
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.length">
+            <summary>
+            长
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.width">
+            <summary>
+            宽
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.height">
+            <summary>
+            高
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.floorNo">
+            <summary>
+            楼层编号
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.receiptNum">
+            <summary>
+            凭证号
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.spaceStatus">
+            <summary>
+            车位状态,0空位-1占用-2保留-3已预约-4故障
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.frontWheelbase">
+            <summary>
+            前轮距
+            </summary>
+        </member>
+        <member name="F:PLCS7.ParkingSpaceStru.rearWheelbase">
+            <summary>
+            后轮距
+            </summary>
+        </member>
+    </members>
+</doc>

BIN
PLCLinker/newPLCConnector/PLC/snap7Enc.dll


+ 22 - 0
PLCLinker/newPLCConnector/Program.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace PLCConnector
+{
+    static class Program
+    {
+        /// <summary>
+        /// 应用程序的主入口点。
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new Form1());
+        }
+    }
+}

+ 36 - 0
PLCLinker/newPLCConnector/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("PLCConnector")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("PLCConnector")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("12254714-e07b-4514-bd5b-edd0a2c71d62")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63 - 0
PLCLinker/newPLCConnector/Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace PLCConnector.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   一个强类型的资源类,用于查找本地化的字符串等。
+    /// </summary>
+    // 此类是由 StronglyTypedResourceBuilder
+    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+    // (以 /str 作为命令选项),或重新生成 VS 项目。
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   返回此类使用的缓存的 ResourceManager 实例。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PLCConnector.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   使用此强类型资源类,为所有资源查找
+        ///   重写当前线程的 CurrentUICulture 属性。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
PLCLinker/newPLCConnector/Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 26 - 0
PLCLinker/newPLCConnector/Properties/Settings.Designer.cs

@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace PLCConnector.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

+ 7 - 0
PLCLinker/newPLCConnector/Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 98 - 0
PLCLinker/newPLCConnector/newPLCConnector.csproj

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{D8626935-71C8-423E-AAD7-D2BDBA809575}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <RootNamespace>PLCConnector</RootNamespace>
+    <AssemblyName>PLCConnector</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="DevComponents.DotNetBar2, Version=12.5.0.2, Culture=neutral, PublicKeyToken=c39c3242a43eee2b" />
+    <Reference Include="PLCS7, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>PLC\PLCS7.dll</HintPath>
+    </Reference>
+    <Reference Include="snap7Enc">
+      <HintPath>PLC\snap7Enc.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="LOG\log.cs" />
+    <Compile Include="LOG\LogManager.cs" />
+    <Compile Include="LOG\LogTest.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 596 - 0
PLCLinker/newPLCS7/PLCS7.cs

@@ -0,0 +1,596 @@
+using snap7Enc;
+using snap7Enc.Types;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Timers;
+
+namespace PLCS7
+{
+    public interface IPLCS7
+    {
+        bool PLCConnect();
+        void PLCDisconnect();
+        bool WriteToPLC(object abstractPLCMsg, PLCDataType whoami);
+        List<object> ReadFromPLC(PLCDataType whichToRead, int index);
+    }
+    public enum PLCDataType
+    {
+        terminal,
+        central,
+        parkingSpace
+    }
+    public abstract class AbstractPLCLinker : IPLCS7
+    {
+        protected const int mainBlockOffset = 52;
+        protected const int parkingSpaceOffset = 18;
+        protected const int terminalLength = 46;
+        protected const int parkingSpaceLength = 48;
+        /// <summary>
+        /// PLC 连接状态flag
+        /// </summary>
+        public bool isConnected = false;
+        /// <summary>
+        /// plc中cpu类型
+        /// </summary>
+        protected CpuType cpu;
+        /// <summary>
+        /// PLC的IP地址
+        /// </summary>
+        protected string ip;
+        /// <summary>
+        /// PLC的端口号
+        /// </summary>
+        protected Int16 rack;
+        /// <summary>
+        /// 工作站号
+        /// </summary>
+        protected Int16 slot;
+        /// <summary>
+        /// 终端DB块iD
+        /// </summary>
+        protected int terminalDB;
+        /// <summary>
+        /// 中心DB块iD
+        /// </summary>
+        protected int centralDB;
+        /// <summary>
+        /// 车位DB块ID
+        /// </summary>
+        protected int parkingSpaceDB;
+        /// <summary>
+        /// 终端个数
+        /// </summary>
+        protected int terminalCount;
+        /// <summary>
+        /// 停车位个数
+        /// </summary>
+        protected int parkingSpaceCount;
+        /// <summary>
+        /// PLC S7连接对象
+        /// </summary>
+        protected static Plc plc = null;
+        /// <summary>
+        /// 用于将写PLC指令排队的阻塞队列
+        /// </summary>
+        protected static BlockingCollection<MsgNodeToWrite> writingBlockingCollection = new BlockingCollection<MsgNodeToWrite>();
+        /// <summary>
+        /// 写线程,控制PLC写入频率
+        /// </summary>
+        protected static Thread writeThread;
+        /// <summary>
+        /// 系统关闭
+        /// </summary>
+        protected bool closed;
+        /// <summary>
+        /// 读写锁
+        /// </summary>
+        protected static object readWriteLock = new object();
+
+        /// <summary>
+        /// 连接
+        /// </summary>
+        /// <returns></returns>
+        public abstract bool PLCConnect();
+        /// <summary>
+        /// 断开连接
+        /// </summary>
+        public abstract void PLCDisconnect();
+        /// <summary>
+        /// 读PLC
+        /// </summary>
+        /// <param name="whichToRead"></param>
+        /// <param name="index"></param>
+        /// <returns></returns>
+        public abstract List<object> ReadFromPLC(PLCDataType whichToRead, int index);
+        /// <summary>
+        /// 写PLC
+        /// </summary>
+        /// <param name="abstractPLCMsg"></param>
+        /// <param name="whoami"></param>
+        /// <returns></returns>
+        public abstract bool WriteToPLC(object abstractPLCMsg, PLCDataType whoami);
+    }
+
+    public class PLCLinker : AbstractPLCLinker
+    {
+        ///// <summary>
+        ///// PLC刷新频率,来自于配置文件
+        ///// </summary>
+        //private int PLC_refresh_interval;
+        ///// <summary>
+        ///// 无法获取配置文件时使用的PLC刷新频率
+        ///// </summary>
+        //private const short PLC_TIME_SCALE = 200;
+
+        //************************************** 方法区 *************************************
+        public void test()
+        {
+            Random rnd = new Random();
+            Task t = Task.Factory.StartNew(() =>
+            {
+                while (true)
+                {
+                    TerminalStru terminal1 = new TerminalStru();
+                    terminal1 = (TerminalStru)ReadStruFromPLC(terminal1, 27, 0);
+                    Console.WriteLine(terminal1.ToString());
+                    Thread.Sleep(200);
+                    terminal1.terminalStatus = (short)rnd.Next(1, 6);
+                    terminal1.licenseCodeA = rnd.Next(3000, 9999);
+                    terminal1.receiptNum = rnd.Next(3000, 9999);
+                    terminal1.licVerification = (short)rnd.Next(1, 555);
+                    WriteStruToPLC(terminal1, 27, 0);
+                    //List<byte> bList = Struct.ToBytes(terminal1).ToList();
+                    //WriteMultipleBytes(27, bList, 0);
+
+                    ////203 chars
+                    //string str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccc";
+                    ////pl.WriteMultipleBytes(1, (Encoding.ASCII.GetBytes(str)).ToList());
+                    //byte[] bytes = pl.ReadMultipleBytes(27, 50).ToArray();
+                    //string str2 = Encoding.ASCII.GetString(bytes);
+                    //Console.WriteLine(str2);
+                    //if (str == str2)
+                    //{
+                    //    Console.WriteLine("equals");
+                    //}
+                    //else
+                    //{
+                    //    Console.WriteLine("error, unequal");
+                    //}
+
+                    Thread.Sleep(2000);
+                }
+            });
+            t.Wait();
+        }
+        /// <summary>
+        /// PLCLinker构造函数
+        /// </summary>
+        /// <param name="cpu"></param>
+        /// <param name="ip"></param>
+        /// <param name="rack"></param>
+        /// <param name="slot"></param>
+        /// <param name="terminalDB"></param>
+        /// <param name="centralDB"></param>
+        /// <param name="parkingSpaceDB"></param>
+        public PLCLinker(CpuType cpu, string ip, short rack, short slot, int terminalDB, int centralDB, int parkingSpaceDB, int terminalCount, int parkingSpaceCount)
+        {
+            this.cpu = cpu;
+            this.ip = ip;
+            this.rack = rack;
+            this.slot = slot;
+            this.terminalDB = terminalDB;
+            this.centralDB = centralDB;
+            this.parkingSpaceDB = parkingSpaceDB;
+            this.terminalCount = terminalCount;
+            this.parkingSpaceCount = parkingSpaceCount;
+            isConnected = PLCConnect();
+        }
+        /// <summary>
+        /// 读取指定数据块中多个字节
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="length"></param>
+        /// <param name="startAddr"></param>
+        /// <returns></returns>
+        private List<byte> ReadMultipleBytes(int db, int length, int startAddr = 0)
+        {
+            List<byte> resultBytes = new List<byte>();
+            int index = startAddr;
+            int remains = length;
+            while (remains > 0)
+            {
+                int maxToRead = Math.Min(remains, 200);
+                try
+                {
+                    byte[] temp = plc.ReadBytes(DataType.DataBlock, db, index, maxToRead);
+                    if (temp == null)
+                        return new List<byte>();
+                    resultBytes.AddRange(temp);
+                    remains -= maxToRead;
+                    index += maxToRead;
+                }
+                catch { }
+            }
+            return resultBytes;
+        }
+        /// <summary>
+        /// 写入指定数据块中多个字节
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="bytesToWrite"></param>
+        /// <param name="startAddr"></param>
+        /// <returns></returns>
+        private ErrorCode WriteMultipleBytes(int db, List<byte> bytesToWrite, int startAddr = 0)
+        {
+            int index = startAddr;
+            int remains = bytesToWrite.Count();
+            try
+            {
+                while (remains > 0)
+                {
+                    int maxToWrite = Math.Min(remains, 200);
+                    ErrorCode ec = plc.WriteBytes(DataType.DataBlock, db, index, bytesToWrite.GetRange(index, maxToWrite).ToArray());
+                    index += maxToWrite;
+                    remains -= maxToWrite;
+                    if (!ec.Equals(ErrorCode.NoError)) { return ec; }
+                }
+            }
+            catch (Exception e) { Console.WriteLine(e.Message); }
+            return ErrorCode.NoError;
+        }
+        /// <summary>
+        /// 从PLC中读取结构体
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="db"></param>
+        /// <param name="startAddr"></param>
+        /// <returns></returns>
+        private object ReadStruFromPLC(object obj, int db, int startAddr = 0)
+        {
+            Type structType = obj.GetType();
+            object returnedObj;
+            try
+            {
+                //returnedObj = plc.ReadStruct(structType, db, startAddr);
+                int numBytes = Struct.GetStructSize(structType);
+                var resultBytes = plc.ReadBytes(DataType.DataBlock, db, startAddr, numBytes);
+                returnedObj = Struct.FromBytes(structType, resultBytes);
+                if (returnedObj != null) { return returnedObj; }
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine(e.Message);
+            }
+            return null;
+            //Console.WriteLine(ts.ToString());
+        }
+        /// <summary>
+        /// 向PLC中写入结构体
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="db"></param>
+        /// <param name="startAddr"></param>
+        private ErrorCode WriteStruToPLC(object obj, int db, int startAddr = 0)
+        {
+            Console.WriteLine("write to PLC");
+            ErrorCode ec = ErrorCode.NoError;
+            try
+            {
+                //ec = plc.WriteStruct(obj, 22, startAddr);
+                List<byte> bList = Struct.ToBytes(obj).ToList();
+                ec = WriteMultipleBytes(db, bList, startAddr);
+            }
+            catch (Exception e) { Console.WriteLine(ec.ToString() + "," + e.Message); }
+            return ec;
+        }
+        private short BytesRevert(short num)
+        {
+            byte[] temp = BitConverter.GetBytes(num);
+            Array.Reverse(temp);
+            return BitConverter.ToInt16(temp, 0);
+        }
+        private int BytesRevert(int num)
+        {
+            byte[] temp = BitConverter.GetBytes(num);
+            Array.Reverse(temp);
+            return BitConverter.ToInt32(temp, 0);
+        }
+        /// <summary>
+        /// 从阻塞队列获取需写入PLC数据并写入PLC,时间间隔在线程中控制
+        /// </summary>
+        /// <returns></returns>
+        private bool WriteAccordingly()
+        {
+            MsgNodeToWrite msg = null;
+            try
+            {
+                msg = writingBlockingCollection.Take();
+                //Console.WriteLine("取出后," + writingBlockingCollection.Count);
+            }
+            catch (Exception ex) { Console.WriteLine("获取PLC写对象异常," + ex.Message); }
+            if (msg == null || msg.abstractPLCMsg == null)
+            {
+                Console.WriteLine((msg == null) + "," + (msg.abstractPLCMsg == null));
+                return false;
+            }
+            //更新设备状态
+            isConnected = plc.IsConnected;
+            if (isConnected)
+            {
+                lock (readWriteLock)
+                {
+                    if (msg.abstractPLCMsg.GetType().Equals(typeof(TerminalStru)))
+                    {
+                        TerminalStru ts = (TerminalStru)msg.abstractPLCMsg;
+                        if (ts.terminalID <= 0 || ts.terminalID > terminalCount) { Console.WriteLine("终端id:" + ts.terminalID); return false; }
+                        int offset = terminalLength * (ts.terminalID - 1);
+                        if (msg.whoami.Equals(PLCDataType.central))
+                        {
+                            if (ts.paymentStatus != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 28 + offset, BitConverter.GetBytes(BytesRevert(ts.paymentStatus))); }
+                            if (ts.licVerification != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 30 + offset, BitConverter.GetBytes(BytesRevert(ts.licVerification))); }
+                            if (ts.parkingFee != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 32 + offset, BitConverter.GetBytes(BytesRevert(ts.parkingFee))); }
+                            if (ts.userType != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 34 + offset, BitConverter.GetBytes(BytesRevert(ts.userType))); }
+                        }
+                        else if (msg.whoami.Equals(PLCDataType.terminal))
+                        {
+                            //if (ts.terminalStatus != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 2 + offset, BitConverter.GetBytes(BytesRevert(ts.terminalStatus))); }
+                            if (ts.paymentStatus != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 28 + offset, BitConverter.GetBytes(BytesRevert(ts.paymentStatus))); }
+                            if (ts.btnStatus != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 4 + offset, BitConverter.GetBytes(BytesRevert(ts.btnStatus))); }
+                            if (ts.cmd != (short)-1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 6 + offset, BitConverter.GetBytes(BytesRevert(ts.cmd))); }
+                            if (ts.licenseCodeA != -1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 8 + offset, BitConverter.GetBytes(BytesRevert(ts.licenseCodeA))); }
+                            if (ts.licenseCodeB != -1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 12 + offset, BitConverter.GetBytes(BytesRevert(ts.licenseCodeB))); }
+                            if (ts.licenseCodeC != -1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 16 + offset, BitConverter.GetBytes(BytesRevert(ts.licenseCodeC))); }
+                            if (ts.licenseCodeD != -1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 20 + offset, BitConverter.GetBytes(BytesRevert(ts.licenseCodeD))); }
+                            if (ts.receiptNum != -1) { plc.WriteBytes(DataType.DataBlock, terminalDB, 24 + offset, BitConverter.GetBytes(BytesRevert(ts.receiptNum))); }
+                            if (ts.termHeartbeat != 0) { plc.WriteBytes(DataType.DataBlock, terminalDB, 44 + offset, BitConverter.GetBytes(BytesRevert(ts.termHeartbeat))); }
+                        }
+                    }
+                    else if (msg.abstractPLCMsg.GetType().Equals(typeof(MainBlockStru)) && msg.whoami.Equals(PLCDataType.central))
+                    {
+                        //只允许中控写入
+                        MainBlockStru mbs = (MainBlockStru)msg.abstractPLCMsg;
+                        //byte[] temp = BitConverter.GetBytes(BytesRevert(mbs.licenseReceived));
+                        if (mbs.centralHearbeat != (short)-1) { plc.WriteBytes(DataType.DataBlock, centralDB, mainBlockOffset + 8, BitConverter.GetBytes(BytesRevert(mbs.centralHearbeat))); }
+                        if (mbs.licenseReceived != (short)-1) { plc.WriteBytes(DataType.DataBlock, centralDB, mainBlockOffset, BitConverter.GetBytes(BytesRevert(mbs.licenseReceived))); }
+                        if (mbs.bookParkCmd != (short)-1) { plc.WriteBytes(DataType.DataBlock, centralDB, mainBlockOffset - 4, BitConverter.GetBytes(BytesRevert(mbs.bookParkCmd))); }
+                        if (mbs.bookFetchCmd != (short)-1) { plc.WriteBytes(DataType.DataBlock, centralDB, mainBlockOffset - 2, BitConverter.GetBytes(BytesRevert(mbs.bookFetchCmd))); }
+                        if (mbs.processCompleted != (short)-1) { plc.WriteBytes(DataType.DataBlock, centralDB, 16, BitConverter.GetBytes(BytesRevert(mbs.processCompleted))); }
+                        //ErrorCode ec = plc.WriteBytes(DataType.DataBlock, centralDB, mainBlockOffset, temp);
+                        //if (!ec.Equals(ErrorCode.NoError)) { return false; }
+                    }
+                    else if (msg.abstractPLCMsg.GetType().Equals(typeof(ParkingSpaceStru)) && msg.whoami.Equals(PLCDataType.central))
+                    {
+                        //只允许中控写入,中控只允许写车位状态
+                        ParkingSpaceStru pss = (ParkingSpaceStru)msg.abstractPLCMsg;
+                        int offset = parkingSpaceLength * (pss.parkingSpace - 1) + parkingSpaceOffset;
+                        byte[] temp = BitConverter.GetBytes(BytesRevert(pss.spaceStatus));
+                        ErrorCode ec = plc.WriteBytes(DataType.DataBlock, parkingSpaceDB, offset, temp);
+                        if (!ec.Equals(ErrorCode.NoError)) { return false; }
+                    }
+                    else { Console.WriteLine(msg.whoami); return false; }
+                }
+            }
+            else { Console.WriteLine("掉线"); return false; }
+            return true;
+        }
+
+        /// <summary>
+        /// 读取PLC数据块
+        /// </summary>
+        /// <param name="whichToRead"></param>
+        /// <param name="index"></param>
+        /// <returns></returns>
+        public override List<object> ReadFromPLC(PLCDataType whichToRead, int index)
+        {
+            //更新设备状态
+            isConnected = plc.IsConnected;
+            List<object> result = new List<object>();
+            if (!isConnected)
+            {
+                PLCConnect();
+            }
+            if (isConnected)
+            {
+                lock (readWriteLock)
+                {
+                    switch (whichToRead)
+                    {
+                        case PLCDataType.central:
+                            object obj = ReadStruFromPLC(new MainBlockStru(), centralDB);
+                            if (obj != null) { result.Add(obj); }
+                            break;
+                        case PLCDataType.terminal:
+                            TerminalStru ts = new TerminalStru();
+                            //index 在合理范围读取单一元素,否则全部读取
+                            if (index > 0 && index < terminalCount)
+                            {
+                                obj = ReadStruFromPLC(ts, terminalDB, Struct.GetStructSize(ts.GetType()) * (index - 1));
+                                if (obj != null) { result.Add(obj); }
+                            }
+                            else
+                            {
+                                for (int i = 0; i < terminalCount; i++)
+                                {
+                                    obj = ReadStruFromPLC(ts, terminalDB, Struct.GetStructSize(ts.GetType()) * i);
+                                    if (obj != null) { result.Add(obj); }
+                                }
+                            }
+                            break;
+                        case PLCDataType.parkingSpace:
+                            ParkingSpaceStru pss = new ParkingSpaceStru();
+                            //index 在合理范围读取单一元素,否则全部读取
+                            if (index > 0 && index < parkingSpaceCount)
+                            {
+                                obj = ReadStruFromPLC(pss, parkingSpaceDB, Struct.GetStructSize(pss.GetType()) * (index - 1));
+                                if (obj != null) { result.Add(obj); }
+                            }
+                            else
+                            {
+                                for (int i = 0; i < parkingSpaceCount; i++)
+                                {
+                                    obj = ReadStruFromPLC(pss, parkingSpaceDB, Struct.GetStructSize(pss.GetType()) * i);
+                                    if (obj != null) { result.Add(obj); }
+                                }
+                            }
+                            break;
+                        default:
+                            Console.WriteLine("wrong type");
+                            break;
+                    }
+                }
+            }
+            return result;
+        }
+        /// <summary>
+        /// 写入PLC,其中可写入但不需写入字段请赋值为-1
+        /// </summary>
+        /// <param name="abstractPLCMsg"></param>
+        /// <param name="whoami"></param>
+        /// <returns></returns>
+        public override bool WriteToPLC(object abstractPLCMsg, PLCDataType whoami)
+        {
+            //更新设备状态
+            isConnected = plc.IsConnected;
+            if (abstractPLCMsg != null)
+            {
+                writingBlockingCollection.Add(new MsgNodeToWrite(abstractPLCMsg, whoami));
+                //Console.WriteLine("加入后," + writingBlockingCollection.Count);
+                return true;
+            }
+            else
+                return false;
+        }
+        /// <summary>
+        /// 连接PLC
+        /// </summary>
+        /// <returns></returns>
+        public override bool PLCConnect()
+        {
+            closed = false;
+            writeThread = new Thread(() =>
+            {
+                //Stopwatch stopwatch = new Stopwatch();
+                while (!closed)
+                {
+                    //stopwatch.Restart();
+                    bool result = WriteAccordingly();
+                    if (!result)
+                        Console.WriteLine("写PLC操作异常");
+                    Thread.Sleep(20);
+                    //stopwatch.Stop();
+                    //Console.WriteLine(stopwatch.ElapsedMilliseconds / 1000.0f);
+                }
+            });
+            writeThread.IsBackground = true;
+            writeThread.Priority = ThreadPriority.AboveNormal;
+            writeThread.Start();
+
+            if (plc == null)
+            {
+                plc = new Plc(cpu, ip, rack, slot);
+            }
+            if (plc != null)
+            {
+                ErrorCode err = plc.Open();
+                if (err != ErrorCode.NoError) { Console.WriteLine("connection error"); isConnected = false; }
+                else { Console.WriteLine("connected"); isConnected = true; }
+            }
+            else { isConnected = false; }
+            return isConnected;
+        }
+        /// <summary>
+        /// 关闭PLC连接
+        /// </summary>
+        public override void PLCDisconnect()
+        {
+            //try
+            //{
+            //    if (writeThread != null)
+            //        writeThread.Abort();
+            //}
+            //catch (Exception ex) { Console.WriteLine("强制终止写PLC线程," + ex.Message); }
+            closed = true;
+            if (plc != null)
+            {
+                plc.Close();
+            }
+        }
+
+        /// <summary>
+        /// 根据地址偏移量写入PLC
+        /// </summary>
+        /// <param name="whichToWrite"></param>
+        /// <param name="offset"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public bool WriteAccordingToOffset(PLCDataType whichToWrite, int offset, object value)
+        {
+            isConnected = plc.IsConnected;
+            if (value == null)
+                return false;
+            if (isConnected)
+            {
+                ErrorCode ec = ErrorCode.NoError;
+                switch (whichToWrite)
+                {
+                    case PLCDataType.terminal:
+                        if (value.GetType().Equals(typeof(int)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, terminalDB, offset, BitConverter.GetBytes(BytesRevert((int)value)));
+                        }
+                        else if (value.GetType().Equals(typeof(short)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, terminalDB, offset, BitConverter.GetBytes(BytesRevert((short)value)));
+                        }
+                        if (ec.Equals(ErrorCode.NoError)) { return true; }
+                        else { return false; }
+                        break;
+                    case PLCDataType.central:
+                        if (value.GetType().Equals(typeof(int)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, centralDB, offset, BitConverter.GetBytes(BytesRevert((int)value)));
+                        }
+                        else if (value.GetType().Equals(typeof(short)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, centralDB, offset, BitConverter.GetBytes(BytesRevert((short)value)));
+                        }
+                        if (ec.Equals(ErrorCode.NoError)) { return true; }
+                        else { return false; }
+                        break;
+                    case PLCDataType.parkingSpace:
+                        if (value.GetType().Equals(typeof(int)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, parkingSpaceDB, offset, BitConverter.GetBytes(BytesRevert((int)value)));
+                        }
+                        else if (value.GetType().Equals(typeof(short)))
+                        {
+                            ec = plc.WriteBytes(DataType.DataBlock, parkingSpaceDB, offset, BitConverter.GetBytes(BytesRevert((short)value)));
+                        }
+                        if (ec.Equals(ErrorCode.NoError)) { return true; }
+                        else { return false; }
+                        break;
+                }
+            }
+            return false;
+        }
+    }
+
+    public class MsgNodeToWrite
+    {
+        public object abstractPLCMsg;
+        public PLCDataType whoami;
+        public MsgNodeToWrite(object abstractPLCMsg, PLCDataType whoami)
+        {
+            this.abstractPLCMsg = abstractPLCMsg;
+            this.whoami = whoami;
+        }
+    }
+}

+ 36 - 0
PLCLinker/newPLCS7/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("PLCS7")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("PLCS7")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("ad3b33a7-4131-416f-b08e-6c87df56f44e")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 315 - 0
PLCLinker/newPLCS7/entity.cs

@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PLCS7
+{
+    /// <summary>
+    /// 终端数据块结构体
+    /// </summary>
+    public struct TerminalStru
+    {
+        /// <summary>
+        /// 终端ID号
+        /// </summary>
+        public short terminalID;
+        /// <summary>
+        /// 终端状态,0暂停,1停车,2取车
+        /// </summary>
+        public short terminalStatus;//终端写入
+        /// <summary>
+        /// 按钮状态,0缺省,1非注册,2注册,3预约
+        /// </summary>
+        public short btnStatus;//终端写入
+        /// <summary>
+        /// 停取指令,0缺省,1停车,2取车
+        /// </summary>
+        public short cmd;//终端写入
+        /// <summary>
+        /// 注册用户UserID
+        /// </summary>
+        public int licenseCodeA;//终端写入
+        /// <summary>
+        /// 注册用户号牌地域标记
+        /// </summary>
+        public int licenseCodeB;//终端写入
+        /// <summary>
+        /// 注册用户号牌后半部分A
+        /// </summary>
+        public int licenseCodeC;//终端写入
+        /// <summary>
+        /// 注册用户号牌后半部分B
+        /// </summary>
+        public int licenseCodeD;//终端写入
+        /// <summary>
+        /// 凭证号
+        /// </summary>
+        public int receiptNum;//终端写入,24
+        /// <summary>
+        /// 支付状态,0-1失败-2成功-3管理员放行
+        /// </summary>
+        public short paymentStatus;//中控写入,28
+        /// <summary>
+        /// 1-成功,2-号牌比对不成功
+        /// </summary>
+        public short licVerification;//中控写入,30
+        /// <summary>
+        /// 停车费用,0-99999
+        /// </summary>
+        public short parkingFee;//中控写入
+        /// <summary>
+        /// 用户类型,0-1普通-2月卡-3季卡-4年卡VIP
+        /// </summary>
+        public short userType;//中控写入,34
+        /// <summary>
+        /// X坐标
+        /// </summary>
+        public short coordX;//PLC
+        /// <summary>
+        /// Y坐标
+        /// </summary>
+        public short coordY;//PLC
+        /// <summary>
+        /// 地感信号
+        /// </summary>
+        public short groundStatus;
+        /// <summary>
+        /// 启动对应号牌机
+        /// </summary>
+        public short numMachineLaunch;
+        /// <summary>
+        /// 终端心跳
+        /// </summary>
+        public short termHeartbeat;
+
+        public override string ToString()
+        {
+            return "[终端id(0):" + terminalID + ",终端状态(2):" + terminalStatus + ",按钮状态(4):" + btnStatus + ",终端指令(6):" + cmd + ",用户id(8):" + licenseCodeA + ","
+                + licenseCodeB + "," + licenseCodeC + "," + licenseCodeD + ",凭证号(24):" + receiptNum + ",支付状态(28):" + paymentStatus
+                + ",号牌验证(30):" + licVerification + ",停车费用(32):" + parkingFee + ",用户类型(34):" + userType + ",X坐标(36):" + coordX + ",Y坐标(38):" + coordY +
+                ",地感信号(40):" + groundStatus + ",启动号牌机(42):" + numMachineLaunch + ",终端心跳(44):" + termHeartbeat + "]";
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null) return false;
+            else if ((object)this == obj) return true;
+            else if (obj.GetType().Equals(typeof(TerminalStru)))
+            {
+                TerminalStru ts = (TerminalStru)obj;
+                if (ts.ToString().Equals(ToString())) return true;
+                else return false;
+            }
+            else return false;
+        }
+
+        public override int GetHashCode()
+        {
+            return (ToString()).GetHashCode();
+        }
+    }
+
+    /// <summary>
+    /// 中控与PLC交互使用数据块的结构体
+    /// </summary>
+    public struct MainBlockStru
+    {
+        /// <summary>
+        /// 终端ID号
+        /// </summary>
+        public short terminalID;
+        /// <summary>
+        /// 号牌机启动指令
+        /// </summary>
+        public short numMachineLaunch;
+        /// <summary>
+        /// 摆扫启动指令
+        /// </summary>
+        public short sweepLaserLaunch;
+        /// <summary>
+        /// 轮距启动指令
+        /// </summary>
+        public short wheelbaseLaserLaunch;
+        /// <summary>
+        /// 急停
+        /// </summary>
+        public short stop;
+        /// <summary>
+        /// 就绪
+        /// </summary>
+        public short ready;
+        /// <summary>
+        /// 停车运行
+        /// </summary>
+        public short parkingRunning;
+        /// <summary>
+        /// 取车运行
+        /// </summary>
+        public short fetchingRunning;
+        /// <summary>
+        /// 流程完成
+        /// </summary>
+        public short processCompleted;
+        /// <summary>
+        /// 流程中断
+        /// </summary>
+        public short processStopped;
+        /// <summary>
+        /// 摆扫激光状态
+        /// </summary>
+        public short sweepLaserStatus;
+        /// <summary>
+        /// 轮距雷达状态
+        /// </summary>
+        public short wheelbaseLaserStatus;
+
+        public short groundAStatus;//24
+        public short groundBStatus;
+        public short groundCStatus;
+        public short groundDStatus;
+        public short groundEStatus;
+        public short groundFStatus;
+        public short arriveAAndOpen;
+        public short arriveBAndOpen;
+        public short arriveCAndOpen;
+        public short arriveDAndOpen;
+        public short arriveEAndOpen;
+        public short arriveFAndOpen;
+        //public short leaveAAndOpen;
+        //public short leaveBAndOpen;
+        //public short leaveCAndOpen;
+        public short bookParkCmd;
+        public short bookFetchCmd;
+        /// <summary>
+        /// 号牌机获取
+        /// </summary>
+        public short licenseReceived;//中控可写,52
+        /// <summary>
+        /// 本地自动模式
+        /// </summary>
+        public short localAutoMode;
+        /// <summary>
+        /// 云端模式
+        /// </summary>
+        public short remoteMode;
+        /// <summary>
+        /// 本地手动模式
+        /// </summary>
+        public short localManualMode;
+        /// <summary>
+        /// 中控心跳
+        /// </summary>
+        public short centralHearbeat;
+        /// <summary>
+        /// 预约车位总数
+        /// </summary>
+        public short reserveTotalSpace;
+        /// <summary>
+        /// 当前需更新车位ID
+        /// </summary>
+        public short currentParkingSpaceID;//64
+
+        public override string ToString()
+        {
+            return "[id(0):" + terminalID + ",号牌(2):" + numMachineLaunch + ",摆扫(4):" + sweepLaserLaunch + ",轮距(6):" + wheelbaseLaserLaunch + ",急停(8):" + stop
+                + ",就绪(10):" + ready + ",停车启动(12):" + parkingRunning + ",取车启动(14):" + fetchingRunning + ",流程完成(16):" + processCompleted + ",流程中止(18):" +
+                processStopped + ",摆扫状态(20):" + sweepLaserStatus + ",轮距状态(22):" + wheelbaseLaserStatus + ",号牌获取(52):" + licenseReceived
+                + ",本地自动(54):" + localAutoMode + ",远程模式(56):" + remoteMode + ",本地手动(58):" + localManualMode + ",中控心跳(60):" + centralHearbeat + ",预约车位总数(62):" + 
+                reserveTotalSpace + ",待更新车位ID(64):" + currentParkingSpaceID + "," + groundAStatus
+                + "," + groundBStatus + "," + groundCStatus + "," + arriveAAndOpen + "," + arriveBAndOpen + "," + arriveCAndOpen
+                 + "]";
+        }
+        public override int GetHashCode()
+        {
+            return (ToString()).GetHashCode();
+        }
+        public override bool Equals(object obj)
+        {
+            if (obj == null) return false;
+            else if ((object)this == obj) return true;
+            else if (obj.GetType().Equals(typeof(MainBlockStru)))
+            {
+                MainBlockStru ts = (MainBlockStru)obj;
+                if (ts.ToString().Equals(ToString())) return true;
+                else return false;
+            }
+            else return false;
+        }
+    }
+
+    /// <summary>
+    /// 车位单元结构体
+    /// </summary>
+    public struct ParkingSpaceStru
+    {
+        /// <summary>
+        /// 车位编号
+        /// </summary>
+        public short parkingSpace;
+        /// <summary>
+        /// 长
+        /// </summary>
+        public short length;
+        /// <summary>
+        /// 宽
+        /// </summary>
+        public short width;
+        /// <summary>
+        /// 高
+        /// </summary>
+        public short height;
+        /// <summary>
+        /// 楼层编号
+        /// </summary>
+        public short floorNo;
+        public short coordX;
+        public short coordY;
+        /// <summary>
+        /// 凭证号
+        /// </summary>
+        public int receiptNum;
+        /// <summary>
+        /// 车位状态,0空位-1占用-2保留-3已预约-4故障
+        /// </summary>
+        public short spaceStatus;
+        /// <summary>
+        /// 前轮距
+        /// </summary>
+        public short frontWheelbase;
+        /// <summary>
+        /// 后轮距
+        /// </summary>
+        public short rearWheelbase;
+
+        public int startTimeA;
+        public int startTimeB;
+        public int startTimeC;
+        public int endTimeA;
+        public int endTimeB;
+        public int endTimeC;
+
+        public override string ToString()
+        {
+            return "[车位编号(0):" + parkingSpace + ",长(2):" + length + ",宽(4):" + width + ",高(6):" + height + ",楼层(8):" + floorNo + ",X坐标(10):" + coordX + ",Y坐标(12):" + coordY + ",凭证号(14):" + receiptNum
+                + ",车位状态(16):" + spaceStatus + ",前轮距(18):" + frontWheelbase + ",后轮距(20):" + rearWheelbase + "]";
+        }
+        public override int GetHashCode()
+        {
+            return (ToString()).GetHashCode();
+        }
+        public override bool Equals(object obj)
+        {
+            if (obj == null) return false;
+            else if ((object)this == obj) return true;
+            else if (obj.GetType().Equals(typeof(ParkingSpaceStru)))
+            {
+                ParkingSpaceStru ts = (ParkingSpaceStru)obj;
+                if (ts.ToString().Equals(ToString())) return true;
+                else return false;
+            }
+            else return false;
+        }
+    }
+}

+ 53 - 0
PLCLinker/newPLCS7/newPLCS7.csproj

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{A2B15176-879A-4D50-B0CB-D63A0CF2E384}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>PLCS7</RootNamespace>
+    <AssemblyName>PLCS7</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\PLCS7.xml</DocumentationFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="snap7Enc">
+      <HintPath>.\snap7Enc.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="PLCS7.cs" />
+    <Compile Include="entity.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

BIN
PLCLinker/newPLCS7/snap7Enc.dll


+ 252 - 0
PLCLinker/snap7Enc/Conversion.cs

@@ -0,0 +1,252 @@
+using System;
+using System.Globalization;
+
+namespace snap7Enc
+{
+    /// <summary>
+    /// Conversion methods to convert from Siemens numeric format to C# and back
+    /// </summary>
+    public static class Conversion
+    {
+        /// <summary>
+        /// Converts a binary string to Int32 value
+        /// </summary>
+        /// <param name="txt"></param>
+        /// <returns></returns>
+        public static int BinStringToInt32(this string txt)
+        {
+            int ret = 0;
+
+            for (int i = 0; i < txt.Length; i++)
+            {
+                ret = (ret << 1) | ((txt[i] == '1') ? 1 : 0);
+            }
+            return ret;
+        }
+
+        /// <summary>
+        /// Converts a binary string to a byte. Can return null.
+        /// </summary>
+        /// <param name="txt"></param>
+        /// <returns></returns>
+        public static byte? BinStringToByte(this string txt)
+        {
+            if (txt.Length == 8) return (byte)BinStringToInt32(txt);
+            return null;
+        }
+
+        /// <summary>
+        /// Converts the value to a binary string
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static string ValToBinString(this object value)
+        {
+            int cnt = 0;
+            int cnt2 = 0;
+            int x = 0;
+            string txt = "";
+            long longValue = 0;
+
+            try
+            {
+                if (value.GetType().Name.IndexOf("[]") < 0)
+                {
+                    // ist nur ein Wert
+                    switch (value.GetType().Name)
+                    {
+                        case "Byte":
+                            x = 7;
+                            longValue = (long)((byte)value);
+                            break;
+                        case "Int16":
+                            x = 15;
+                            longValue = (long)((Int16)value);
+                            break;
+                        case "Int32":
+                            x = 31;
+                            longValue = (long)((Int32)value);
+                            break;
+                        case "Int64":
+                            x = 63;
+                            longValue = (long)((Int64)value);
+                            break;
+                        default:
+                            throw new Exception();
+                    }
+
+                    for (cnt = x; cnt >= 0; cnt += -1)
+                    {
+                        if (((Int64)longValue & (Int64)Math.Pow(2, cnt)) > 0)
+                            txt += "1";
+                        else
+                            txt += "0";
+                    }
+                }
+                else
+                {
+                    // ist ein Array
+                    switch (value.GetType().Name)
+                    {
+                        case "Byte[]":
+                            x = 7;
+                            byte[] ByteArr = (byte[])value;
+                            for (cnt2 = 0; cnt2 <= ByteArr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((ByteArr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int16[]":
+                            x = 15;
+                            Int16[] Int16Arr = (Int16[])value;
+                            for (cnt2 = 0; cnt2 <= Int16Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int16Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int32[]":
+                            x = 31;
+                            Int32[] Int32Arr = (Int32[])value;
+                            for (cnt2 = 0; cnt2 <= Int32Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int32Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int64[]":
+                            x = 63;
+                            byte[] Int64Arr = (byte[])value;
+                            for (cnt2 = 0; cnt2 <= Int64Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int64Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        default:
+                            throw new Exception();
+                    }
+                }
+                return txt;
+            }
+            catch
+            {
+                return "";
+            }
+        }
+
+        /// <summary>
+        /// Helper to get a bit value given a byte and the bit index.
+        /// Example: DB1.DBX0.5 -> var bytes = ReadBytes(DB1.DBW0); bool bit = bytes[0].SelectBit(5); 
+        /// </summary>
+        /// <param name="data"></param>
+        /// <param name="bitPosition"></param>
+        /// <returns></returns>
+        public static bool SelectBit(this byte data, int bitPosition)
+        {
+            int mask = 1 << bitPosition;
+            int result = data & mask;
+
+            return (result != 0);
+        }
+
+        /// <summary>
+        /// Converts from ushort value to short value; it's used to retrieve negative values from words
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static short ConvertToShort(this ushort input)
+        {
+            short output;
+            output = short.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from short value to ushort value; it's used to pass negative values to DWs
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static ushort ConvertToUshort(this short input)
+        {
+            ushort output;
+            output = ushort.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from UInt32 value to Int32 value; it's used to retrieve negative values from DBDs
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static Int32 ConvertToInt(this uint input)
+        {
+            int output;
+            output = int.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from Int32 value to UInt32 value; it's used to pass negative values to DBDs
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static UInt32 ConvertToUInt(this int input)
+        {
+            uint output;
+            output = uint.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from double to DWord (DBD)
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [Obsolete("Double support is obsolete. Use ConvertToUInt(float) instead.")]
+        public static UInt32 ConvertToUInt(this double input)
+        {
+            uint output;
+            output = snap7Enc.Types.DWord.FromByteArray(snap7Enc.Types.Double.ToByteArray(input));
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from float to DWord (DBD)
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static UInt32 ConvertToUInt(this float input)
+        {
+            uint output;
+            output = snap7Enc.Types.DWord.FromByteArray(snap7Enc.Types.Single.ToByteArray(input));
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from DWord (DBD) to double
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [Obsolete("Double support is obsolete. Use ConvertToFloat(uint) instead.")]
+        public static double ConvertToDouble(this uint input)
+        {
+            double output;
+            output = snap7Enc.Types.Double.FromByteArray(snap7Enc.Types.DWord.ToByteArray(input));
+            return output;
+        }
+
+        /// <summary>
+        /// Converts from DWord (DBD) to float
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static float ConvertToFloat(this uint input)
+        {
+            float output;
+            output = snap7Enc.Types.Single.FromByteArray(snap7Enc.Types.DWord.ToByteArray(input));
+            return output;
+        }
+    }
+}

+ 181 - 0
PLCLinker/snap7Enc/Enums.cs

@@ -0,0 +1,181 @@
+namespace snap7Enc
+{
+    /// <summary>
+    /// Types of S7 cpu supported by the library
+    /// </summary>
+    public enum CpuType
+    {
+        /// <summary>
+        /// S7 200 cpu type
+        /// </summary>
+        S7200 = 0,
+
+        /// <summary>
+        /// S7 300 cpu type
+        /// </summary>
+        S7300 = 10,
+
+        /// <summary>
+        /// S7 400 cpu type
+        /// </summary>
+        S7400 = 20,
+
+        /// <summary>
+        /// S7 1200 cpu type
+        /// </summary>
+        S71200 = 30,
+
+        /// <summary>
+        /// S7 1500 cpu type
+        /// </summary>
+        S71500 = 40,
+    }
+
+    /// <summary>
+    /// Types of error code that can be set after a function is called
+    /// </summary>
+    public enum ErrorCode
+    {
+        /// <summary>
+        /// The function has been executed correctly
+        /// </summary>
+        NoError = 0,
+
+        /// <summary>
+        /// Wrong type of CPU error
+        /// </summary>
+        WrongCPU_Type = 1,
+
+        /// <summary>
+        /// Connection error
+        /// </summary>
+        ConnectionError = 2,
+
+        /// <summary>
+        /// Ip address not available
+        /// </summary>
+        IPAddressNotAvailable,
+
+        /// <summary>
+        /// Wrong format of the variable
+        /// </summary>
+        WrongVarFormat = 10,
+
+        /// <summary>
+        /// Wrong number of received bytes
+        /// </summary>
+        WrongNumberReceivedBytes = 11,
+
+        /// <summary>
+        /// Error on send data
+        /// </summary>
+        SendData = 20,
+
+        /// <summary>
+        /// Error on read data
+        /// </summary>
+        ReadData = 30,
+
+        /// <summary>
+        /// Error on write data
+        /// </summary>
+        WriteData = 50
+    }
+
+    /// <summary>
+    /// Types of memory area that can be read
+    /// </summary>
+    public enum DataType
+    {
+        /// <summary>
+        /// Input area memory
+        /// </summary>
+        Input = 129,
+
+        /// <summary>
+        /// Output area memory
+        /// </summary>
+        Output = 130,
+
+        /// <summary>
+        /// Merkers area memory (M0, M0.0, ...)
+        /// </summary>
+        Memory = 131,
+
+        /// <summary>
+        /// DB area memory (DB1, DB2, ...)
+        /// </summary>
+        DataBlock = 132,
+
+        /// <summary>
+        /// Timer area memory(T1, T2, ...)
+        /// </summary>
+        Timer = 29,
+
+        /// <summary>
+        /// Counter area memory (C1, C2, ...)
+        /// </summary>
+        Counter = 28
+    }
+
+    /// <summary>
+    /// Types
+    /// </summary>
+    public enum VarType
+    {
+        /// <summary>
+        /// S7 Bit variable type (bool)
+        /// </summary>
+        Bit,
+
+        /// <summary>
+        /// S7 Byte variable type (8 bits)
+        /// </summary>
+        Byte,
+
+        /// <summary>
+        /// S7 Word variable type (16 bits, 2 bytes)
+        /// </summary>
+        Word,
+
+        /// <summary>
+        /// S7 DWord variable type (32 bits, 4 bytes)
+        /// </summary>
+        DWord,
+
+        /// <summary>
+        /// S7 Int variable type (16 bits, 2 bytes)
+        /// </summary>
+        Int,
+
+        /// <summary>
+        /// DInt variable type (32 bits, 4 bytes)
+        /// </summary>
+        DInt,
+
+        /// <summary>
+        /// Real variable type (32 bits, 4 bytes)
+        /// </summary>
+        Real,
+
+        /// <summary>
+        /// String variable type (variable)
+        /// </summary>
+        String,
+
+        /// <summary>
+        /// String variable type (variable)
+        /// </summary>
+        StringEx,
+
+        /// <summary>
+        /// Timer variable type
+        /// </summary>
+        Timer,
+
+        /// <summary>
+        /// Counter variable type
+        /// </summary>
+        Counter
+    }
+}

+ 197 - 0
PLCLinker/snap7Enc/PLCAddress.cs

@@ -0,0 +1,197 @@
+namespace snap7Enc
+{
+    internal class PLCAddress
+    {
+        private DataType dataType;
+        private int dbNumber;
+        private int startByte;
+        private int bitNumber;
+        private VarType varType;
+
+        public DataType DataType
+        {
+            get => dataType;
+            set => dataType = value;
+        }
+
+        public int DbNumber
+        {
+            get => dbNumber;
+            set => dbNumber = value;
+        }
+
+        public int StartByte
+        {
+            get => startByte;
+            set => startByte = value;
+        }
+
+        public int BitNumber
+        {
+            get => bitNumber;
+            set => bitNumber = value;
+        }
+
+        public VarType VarType
+        {
+            get => varType;
+            set => varType = value;
+        }
+
+        public PLCAddress(string address)
+        {
+            Parse(address, out dataType, out dbNumber, out varType, out startByte, out bitNumber);
+        }
+
+        public static void Parse(string input, out DataType dataType, out int dbNumber, out VarType varType, out int address, out int bitNumber)
+        {
+            bitNumber = -1;
+            dbNumber = 0;
+
+            switch (input.Substring(0, 2))
+            {
+                case "DB":
+                    string[] strings = input.Split(new char[] { '.' });
+                    if (strings.Length < 2)
+                        throw new InvalidAddressException("To few periods for DB address");
+
+                    dataType = DataType.DataBlock;
+                    dbNumber = int.Parse(strings[0].Substring(2));
+                    address = int.Parse(strings[1].Substring(3));
+
+                    string dbType = strings[1].Substring(0, 3);
+                    switch (dbType)
+                    {
+                        case "DBB":
+                            varType = VarType.Byte;
+                            return;
+                        case "DBW":
+                            varType = VarType.Word;
+                            return;
+                        case "DBD":
+                            varType = VarType.DWord;
+                            return;
+                        case "DBX":
+                            bitNumber = int.Parse(strings[2]);
+                            if (bitNumber > 7)
+                                throw new InvalidAddressException("Bit can only be 0-7");
+                            varType = VarType.Bit;
+                            return;
+                        default:
+                            throw new InvalidAddressException();
+                    }
+                case "EB":
+                    // Input byte
+                    dataType = DataType.Input;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Byte;
+                    return;
+                case "EW":
+                    // Input word
+                    dataType = DataType.Input;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Word;
+                    return;
+                case "ED":
+                    // Input double-word
+                    dataType = DataType.Input;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.DWord;
+                    return;
+                case "AB":
+                    // Output byte
+                    dataType = DataType.Output;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Byte;
+                    return;
+                case "AW":
+                    // Output word
+                    dataType = DataType.Output;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Word;
+                    return;
+                case "AD":
+                    // Output double-word
+                    dataType = DataType.Output;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.DWord;
+                    return;
+                case "MB":
+                    // Memory byte
+                    dataType = DataType.Memory;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Byte;
+                    return;
+                case "MW":
+                    // Memory word
+                    dataType = DataType.Memory;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.Word;
+                    return;
+                case "MD":
+                    // Memory double-word
+                    dataType = DataType.Memory;
+                    dbNumber = 0;
+                    address = int.Parse(input.Substring(2));
+                    varType = VarType.DWord;
+                    return;
+                default:
+                    switch (input.Substring(0, 1))
+                    {
+                        case "E":
+                        case "I":
+                            // Input
+                            dataType = DataType.Input;
+                            varType = VarType.Bit;
+                            break;
+                        case "A":
+                        case "O":
+                            // Output
+                            dataType = DataType.Output;
+                            varType = VarType.Bit;
+                            break;
+                        case "M":
+                            // Memory
+                            dataType = DataType.Memory;
+                            varType = VarType.Byte;
+                            break;
+                        case "T":
+                            // Timer
+                            dataType = DataType.Timer;
+                            dbNumber = 0;
+                            address = int.Parse(input.Substring(1));
+                            varType = VarType.Timer;
+                            return;
+                        case "Z":
+                        case "C":
+                            // Counter
+                            dataType = DataType.Timer;
+                            dbNumber = 0;
+                            address = int.Parse(input.Substring(1));
+                            varType = VarType.Counter;
+                            return;
+                        default:
+                            throw new InvalidAddressException(string.Format("{0} is not a valid address", input.Substring(0, 1)));
+                    }
+
+                    string txt2 = input.Substring(1);
+                    if (txt2.IndexOf(".") == -1)
+                        throw new InvalidAddressException("To few periods for DB address");
+
+                    address = int.Parse(txt2.Substring(0, txt2.IndexOf(".")));
+                    bitNumber = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1));
+                    if (bitNumber > 7)
+                        throw new InvalidAddressException("Bit can only be 0-7");
+                    return;
+            }
+        }
+    }
+}

+ 92 - 0
PLCLinker/snap7Enc/PLCExceptions.cs

@@ -0,0 +1,92 @@
+using System;
+#if NET_FULL
+using System.Runtime.Serialization;    
+#endif
+
+
+namespace snap7Enc
+{
+    internal class WrongNumberOfBytesException : Exception
+    {
+        public WrongNumberOfBytesException() : base()
+        {
+        }
+
+        public WrongNumberOfBytesException(string message) : base(message)
+        {
+        }
+
+        public WrongNumberOfBytesException(string message, Exception innerException) : base(message, innerException)
+        {
+        }
+
+        #if NET_FULL
+        protected WrongNumberOfBytesException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+        #endif
+    }
+
+    internal class InvalidAddressException : Exception
+    {
+        public InvalidAddressException() : base ()
+        {
+        }
+
+        public InvalidAddressException(string message) : base(message)
+        {
+        }
+
+        public InvalidAddressException(string message, Exception innerException) : base(message, innerException)
+        {
+        }
+
+        #if NET_FULL
+        protected InvalidAddressException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+        #endif
+    }
+
+    internal class InvalidVariableTypeException : Exception
+    {
+        public InvalidVariableTypeException() : base()
+        {
+        }
+
+        public InvalidVariableTypeException(string message) : base(message)
+        {
+        }
+
+        public InvalidVariableTypeException(string message, Exception innerException) : base(message, innerException)
+        {
+        }
+
+        #if NET_FULL
+        protected InvalidVariableTypeException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+        #endif
+    }
+
+    internal class TPKTInvalidException : Exception
+    {
+        public TPKTInvalidException() : base()
+        {
+        }
+
+        public TPKTInvalidException(string message) : base(message)
+        {
+        }
+
+        public TPKTInvalidException(string message, Exception innerException) : base(message, innerException)
+        {
+        }
+
+        #if NET_FULL
+        protected TPKTInvalidException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+        #endif
+    }
+}

+ 174 - 0
PLCLinker/snap7Enc/Plc.cs

@@ -0,0 +1,174 @@
+using Sharp7;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace snap7Enc
+{
+    public class Plc : IDisposable
+    {
+        private S7Client Client;
+        /// <summary>
+        /// IP address of the PLC
+        /// </summary>
+        public string IP { get; private set; }
+
+        /// <summary>
+        /// CPU type of the PLC
+        /// </summary>
+        public CpuType CPU { get; private set; }
+
+        /// <summary>
+        /// Rack of the PLC
+        /// </summary>
+        public Int16 Rack { get; private set; }
+
+        /// <summary>
+        /// Slot of the CPU of the PLC
+        /// </summary>
+        public Int16 Slot { get; private set; }
+
+        /// <summary>
+        /// Checks if the socket is connected and polls the other peer (the PLC) to see if it's connected.
+        /// This is the variable that you should continously check to see if the communication is working
+        /// See also: http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c
+        /// </summary>
+        public bool IsConnected
+        {
+            get
+            {
+                try
+                {
+                    return Client.Connected;
+                }
+                catch { return false; }
+            }
+        }
+
+        /// <summary>
+        /// Creates a PLC object with all the parameters needed for connections.
+        /// For S7-1200 and S7-1500, the default is rack = 0 and slot = 0.
+        /// You need slot > 0 if you are connecting to external ethernet card (CP).
+        /// For S7-300 and S7-400 the default is rack = 0 and slot = 2.
+        /// </summary>
+        /// <param name="cpu">CpuType of the PLC (select from the enum)</param>
+        /// <param name="ip">Ip address of the PLC</param>
+        /// <param name="rack">rack of the PLC, usually it's 0, but check in the hardware configuration of Step7 or TIA portal</param>
+        /// <param name="slot">slot of the CPU of the PLC, usually it's 2 for S7300-S7400, 0 for S7-1200 and S7-1500.
+        ///  If you use an external ethernet card, this must be set accordingly.</param>
+        public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot)
+        {
+            if (!Enum.IsDefined(typeof(CpuType), cpu))
+                throw new ArgumentException($"The value of argument '{nameof(cpu)}' ({cpu}) is invalid for Enum type '{typeof(CpuType).Name}'.", nameof(cpu));
+
+            if (string.IsNullOrEmpty(ip))
+                throw new ArgumentException("IP address must valid.", nameof(ip));
+
+            CPU = cpu;
+            IP = ip;
+            Rack = rack;
+            Slot = slot;
+            Client = new S7Client();
+        }
+
+        public byte[] ReadBytes(DataType dataType, int db, int startByteAdr, int count)
+        {
+            try { 
+            if (Client != null)
+            {
+                byte[] buffer = new byte[count];
+                if (dataType == DataType.DataBlock)
+                {
+                    Client.DBRead(db, startByteAdr, count, buffer);
+                    return buffer;
+                }
+            }
+            }
+            catch (Exception ex) { Console.WriteLine("snap7读异常," + ex.Message + "," + ex.StackTrace); }
+            return null;
+        }
+
+        public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
+        {
+            try
+            {
+                if (Client != null)
+                {
+                    if (dataType == DataType.DataBlock)
+                    {
+                        int result = Client.DBWrite(db, startByteAdr, value.Length, value);
+                        if (result == 0)
+                            return ErrorCode.NoError;
+                    }
+                }
+            }
+            catch(Exception ex) { Console.WriteLine("snap7写异常,"+ex.Message+","+ex.StackTrace); }
+            return ErrorCode.ConnectionError;
+        }
+
+        /// <summary>
+        /// Open connection to PLC
+        /// </summary>
+        public ErrorCode Open()
+        {
+            int result = -1;
+            if (Client != null)
+            {
+                result = Client.ConnectTo(IP, Rack, Slot);
+            }
+            return result == 0 ? ErrorCode.NoError : ErrorCode.ConnectionError;
+        }
+
+        /// <summary>
+        /// Close connection to PLC
+        /// </summary>
+        public void Close()
+        {
+            if (Client != null)
+            {
+                if (Client.Connected) Client.Disconnect();
+            }
+        }
+
+        #region IDisposable Support
+        private bool disposedValue = false; // To detect redundant calls
+
+        /// <summary>
+        /// Dispose Plc Object
+        /// </summary>
+        /// <param name="disposing"></param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    Close();
+                }
+
+                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+                // TODO: set large fields to null.
+
+                disposedValue = true;
+            }
+        }
+
+        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
+        // ~Plc() {
+        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+        //   Dispose(false);
+        // }
+
+        // This code added to correctly implement the disposable pattern.
+        void IDisposable.Dispose()
+        {
+            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+            Dispose(true);
+            // TODO: uncomment the following line if the finalizer is overridden above.
+            // GC.SuppressFinalize(this);
+        }
+        #endregion
+    }
+}

+ 39 - 0
PLCLinker/snap7Enc/PlcException.cs

@@ -0,0 +1,39 @@
+using System;
+
+namespace snap7Enc
+{
+    #if NET_FULL
+    [Serializable]
+    #endif
+    public class PlcException : Exception
+    {
+        public ErrorCode ErrorCode { get; }
+
+        public PlcException(ErrorCode errorCode) : this(errorCode, $"PLC communication failed with error '{errorCode}'.")
+        {
+        }
+
+        public PlcException(ErrorCode errorCode, Exception innerException) : this(errorCode, innerException.Message,
+            innerException)
+        {
+        }
+
+        public PlcException(ErrorCode errorCode, string message) : base(message)
+        {
+            ErrorCode = errorCode;
+        }
+
+        public PlcException(ErrorCode errorCode, string message, Exception inner) : base(message, inner)
+        {
+            ErrorCode = errorCode;
+        }
+
+        #if NET_FULL
+        protected PlcException(System.Runtime.Serialization.SerializationInfo info,
+            System.Runtime.Serialization.StreamingContext context) : base(info, context)
+        {
+            ErrorCode = (ErrorCode) info.GetInt32(nameof(ErrorCode));
+        }
+        #endif
+    }
+}

+ 36 - 0
PLCLinker/snap7Enc/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("snap7Enc")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("snap7Enc")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("c1364cbb-83d7-44c7-b982-5a09f7ec1ac0")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

File diff suppressed because it is too large
+ 3754 - 0
PLCLinker/snap7Enc/Sharp7.cs


+ 27 - 0
PLCLinker/snap7Enc/Types/Bit.cs

@@ -0,0 +1,27 @@
+using System.Collections;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Bit from S7 plc to C#.
+    /// </summary>
+    public static class Bit
+    {
+        /// <summary>
+        /// Converts a Bit to bool
+        /// </summary>
+        public static bool FromByte(byte v, byte bitAdr)
+        {
+            return (((int)v & (1 << bitAdr)) != 0);
+        }
+
+        /// <summary>
+        /// Converts an array of bytes to a BitArray
+        /// </summary>
+        public static BitArray ToBitArray(byte[] bytes)
+        {
+            BitArray bitArr = new BitArray(bytes);
+            return bitArr;
+        }
+    }
+}

+ 33 - 0
PLCLinker/snap7Enc/Types/Boolean.cs

@@ -0,0 +1,33 @@
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the methods to read, set and reset bits inside bytes
+    /// </summary>
+    public static class Boolean
+    {
+        /// <summary>
+        /// Returns the value of a bit in a bit, given the address of the bit
+        /// </summary>
+        public static bool GetValue(byte value, int bit)
+        {
+            return (((int)value & (1 << bit)) != 0);
+        }
+
+        /// <summary>
+        /// Sets the value of a bit to 1 (true), given the address of the bit
+        /// </summary>
+        public static byte SetBit(byte value, int bit)
+        {
+            return (byte)((value | (1 << bit)) & 0xFF);
+        }
+
+        /// <summary>
+        /// Resets the value of a bit to 0 (false), given the address of the bit
+        /// </summary>
+        public static byte ClearBit(byte value, int bit)
+        {
+            return (byte)((value | (~(1 << bit))) & 0xFF);
+        }
+
+    }
+}

+ 33 - 0
PLCLinker/snap7Enc/Types/Byte.cs

@@ -0,0 +1,33 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the methods to convert from bytes to byte arrays
+    /// </summary>
+    public static class Byte
+    {
+        /// <summary>
+        /// Converts a byte to byte array
+        /// </summary>
+        public static byte[] ToByteArray(byte value)
+        {
+            return new byte[] { value }; ;
+        }
+       
+        /// <summary>
+        /// Converts a byte array to byte
+        /// </summary>
+        /// <param name="bytes"></param>
+        /// <returns></returns>
+        public static byte FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 1)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 1 bytes.");
+            }
+            return bytes[0];
+        }
+        
+    }
+}

+ 58 - 0
PLCLinker/snap7Enc/Types/ByteArray.cs

@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+
+namespace snap7Enc.Types
+{
+    class ByteArray
+    {
+        List<byte> list = new List<byte>();
+
+        public byte this[int index]
+        {
+            get => list[index];
+            set => list[index] = value;
+        }
+
+        public byte[] Array
+        {
+            get { return list.ToArray(); }
+        }
+
+        public int Length => list.Count;
+
+        public ByteArray()
+        {
+            list = new List<byte>();
+        }
+
+        public ByteArray(int size)
+        {
+            list = new List<byte>(size);
+        }
+        
+        public void Clear()
+        {
+            list = new List<byte>();
+        }
+
+        public void Add(byte item)
+        {
+            list.Add(item);
+        }
+
+        public void AddWord(ushort value)
+        {
+            list.Add((byte) (value >> 8));
+            list.Add((byte) value);
+        }
+
+        public void Add(byte[] items)
+        {
+            list.AddRange(items);
+        }
+
+        public void Add(ByteArray byteArray)
+        {
+            list.AddRange(byteArray.Array);
+        }
+    }
+}

+ 344 - 0
PLCLinker/snap7Enc/Types/Class.cs

@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the methods to convert a C# class to S7 data types
+    /// </summary>
+    public static class Class
+    {
+        private static IEnumerable<PropertyInfo> GetAccessableProperties(Type classType)
+        {
+            return classType
+#if NETSTANDARD1_3
+                .GetTypeInfo().DeclaredProperties.Where(p => p.SetMethod != null);
+#else
+                .GetProperties(
+                    BindingFlags.SetProperty |
+                    BindingFlags.Public |
+                    BindingFlags.Instance)
+                .Where(p => p.GetSetMethod() != null);
+#endif
+
+        }
+
+        private static double GetIncreasedNumberOfBytes(double startingNumberOfBytes, Type type)
+        {
+            double numBytes = startingNumberOfBytes;
+
+            switch (type.Name)
+            {
+                case "Boolean":
+                    numBytes += 0.125;
+                    break;
+                case "Byte":
+                    numBytes = Math.Ceiling(numBytes);
+                    numBytes++;
+                    break;
+                case "Int16":
+                case "UInt16":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    numBytes += 2;
+                    break;
+                case "Int32":
+                case "UInt32":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    numBytes += 4;
+                    break;
+                case "Single":
+                case "Double":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    numBytes += 4;
+                    break;
+                default:
+                    var propertyClass = Activator.CreateInstance(type);
+                    numBytes += GetClassSize(propertyClass);
+                    break;
+            }
+
+            return numBytes;
+        }
+
+        /// <summary>
+        /// Gets the size of the class in bytes.
+        /// </summary>
+        /// <param name="instance">An instance of the class</param>
+        /// <returns>the number of bytes</returns>
+        public static int GetClassSize(object instance)
+        {
+            double numBytes = 0.0;
+
+            var properties = GetAccessableProperties(instance.GetType());
+            foreach (var property in properties)
+            {
+                if (property.PropertyType.IsArray)
+                {
+                    Type elementType = property.PropertyType.GetElementType();
+                    Array array = (Array)property.GetValue(instance, null);
+                    if (array.Length <= 0)
+                    {
+                        throw new Exception("Cannot determine size of class, because an array is defined which has no fixed size greater than zero.");
+                    }
+
+                    for (int i = 0; i < array.Length; i++)
+                    {
+                        numBytes = GetIncreasedNumberOfBytes(numBytes, elementType);
+                    }
+                }
+                else
+                {
+                    numBytes = GetIncreasedNumberOfBytes(numBytes, property.PropertyType);
+                }
+            }
+            // enlarge numBytes to next even number because S7-Structs in a DB always will be resized to an even byte count
+            numBytes = Math.Ceiling(numBytes);
+            if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                numBytes++;
+            return (int)numBytes;
+        }
+
+        private static object GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
+        {
+            object value = null;
+
+            switch (propertyType.Name)
+            {
+                case "Boolean":
+                    // get the value
+                    int bytePos = (int)Math.Floor(numBytes);
+                    int bitPos = (int)((numBytes - (double)bytePos) / 0.125);
+                    if ((bytes[bytePos] & (int)Math.Pow(2, bitPos)) != 0)
+                        value = true;
+                    else
+                        value = false;
+                    numBytes += 0.125;
+                    break;
+                case "Byte":
+                    numBytes = Math.Ceiling(numBytes);
+                    value = (byte)(bytes[(int)numBytes]);
+                    numBytes++;
+                    break;
+                case "Int16":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    ushort source = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
+                    value = source.ConvertToShort();
+                    numBytes += 2;
+                    break;
+                case "UInt16":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    value = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
+                    numBytes += 2;
+                    break;
+                case "Int32":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    uint sourceUInt = DWord.FromBytes(bytes[(int)numBytes + 3],
+                                                                       bytes[(int)numBytes + 2],
+                                                                       bytes[(int)numBytes + 1],
+                                                                       bytes[(int)numBytes + 0]);
+                    value = sourceUInt.ConvertToInt();
+                    numBytes += 4;
+                    break;
+                case "UInt32":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    value = DWord.FromBytes(
+                        bytes[(int)numBytes],
+                        bytes[(int)numBytes + 1],
+                        bytes[(int)numBytes + 2],
+                        bytes[(int)numBytes + 3]);
+                    numBytes += 4;
+                    break;
+                case "Double":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    value = Double.FromByteArray(
+                        new byte[] {
+                            bytes[(int)numBytes],
+                            bytes[(int)numBytes + 1],
+                            bytes[(int)numBytes + 2],
+                            bytes[(int)numBytes + 3] });
+                    numBytes += 4;
+                    break;
+                case "Single":
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    // hier auswerten
+                    value = Single.FromByteArray(
+                        new byte[] {
+                            bytes[(int)numBytes],
+                            bytes[(int)numBytes + 1],
+                            bytes[(int)numBytes + 2],
+                            bytes[(int)numBytes + 3] });
+                    numBytes += 4;
+                    break;
+                default:
+                    var propClass = Activator.CreateInstance(propertyType);
+                    var buffer = new byte[GetClassSize(propClass)];
+                    if (buffer.Length > 0)
+                    {
+                        Buffer.BlockCopy(bytes, (int)Math.Ceiling(numBytes), buffer, 0, buffer.Length);
+                        FromBytes(propClass, buffer);
+                        value = propClass;
+                        numBytes += buffer.Length;
+                    }
+                    break;
+            }
+
+            return value;
+        }
+
+        /// <summary>
+        /// Sets the object's values with the given array of bytes
+        /// </summary>
+        /// <param name="sourceClass">The object to fill in the given array of bytes</param>
+        /// <param name="bytes">The array of bytes</param>
+        public static void FromBytes(object sourceClass, byte[] bytes)
+        {
+            if (bytes == null)
+                return;
+
+            if (bytes.Length != GetClassSize(sourceClass))
+                return;
+
+            // and decode it
+            double numBytes = 0.0;
+
+            var properties = GetAccessableProperties(sourceClass.GetType());
+            foreach (var property in properties)
+            {
+                if (property.PropertyType.IsArray)
+                {
+                    Array array = (Array)property.GetValue(sourceClass, null);
+                    Type elementType = property.PropertyType.GetElementType();
+                    for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
+                    {
+                        array.SetValue(
+                            GetPropertyValue(elementType, bytes, ref numBytes),
+                            i);
+                    }
+                }
+                else
+                {
+                    property.SetValue(
+                        sourceClass,
+                        GetPropertyValue(property.PropertyType, bytes, ref numBytes),
+                        null);
+                }
+            }
+        }
+
+        private static void ToBytes(object propertyValue, byte[] bytes, ref double numBytes)
+        {
+            int bytePos = 0;
+            int bitPos = 0;
+            byte[] bytes2 = null;
+
+            switch (propertyValue.GetType().Name)
+            {
+                case "Boolean":
+                    // get the value
+                    bytePos = (int)Math.Floor(numBytes);
+                    bitPos = (int)((numBytes - (double)bytePos) / 0.125);
+                    if ((bool)propertyValue)
+                        bytes[bytePos] |= (byte)Math.Pow(2, bitPos);            // is true
+                    else
+                        bytes[bytePos] &= (byte)(~(byte)Math.Pow(2, bitPos));   // is false
+                    numBytes += 0.125;
+                    break;
+                case "Byte":
+                    numBytes = (int)Math.Ceiling(numBytes);
+                    bytePos = (int)numBytes;
+                    bytes[bytePos] = (byte)propertyValue;
+                    numBytes++;
+                    break;
+                case "Int16":
+                    bytes2 = Int.ToByteArray((Int16)propertyValue);
+                    break;
+                case "UInt16":
+                    bytes2 = Word.ToByteArray((UInt16)propertyValue);
+                    break;
+                case "Int32":
+                    bytes2 = DInt.ToByteArray((Int32)propertyValue);
+                    break;
+                case "UInt32":
+                    bytes2 = DWord.ToByteArray((UInt32)propertyValue);
+                    break;
+                case "Double":
+                    bytes2 = Double.ToByteArray((double)propertyValue);
+                    break;
+                case "Single":
+                    bytes2 = Single.ToByteArray((float)propertyValue);
+                    break;
+                default:
+                    bytes2 = ToBytes(propertyValue);
+                    break;
+            }
+
+            if (bytes2 != null)
+            {
+                // add them
+                numBytes = Math.Ceiling(numBytes);
+                if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                    numBytes++;
+                bytePos = (int)numBytes;
+                for (int bCnt = 0; bCnt < bytes2.Length; bCnt++)
+                    bytes[bytePos + bCnt] = bytes2[bCnt];
+                numBytes += bytes2.Length;
+            }
+        }
+
+        /// <summary>
+        /// Creates a byte array depending on the struct type.
+        /// </summary>
+        /// <param name="sourceClass">The struct object</param>
+        /// <returns>A byte array or null if fails.</returns>
+        public static byte[] ToBytes(object sourceClass)
+        {
+            int size = GetClassSize(sourceClass);
+            byte[] bytes = new byte[size];
+            double numBytes = 0.0;
+
+            var properties = GetAccessableProperties(sourceClass.GetType());
+            foreach (var property in properties)
+            {
+                if (property.PropertyType.IsArray)
+                {
+                    Array array = (Array)property.GetValue(sourceClass, null);
+                    Type elementType = property.PropertyType.GetElementType();
+                    for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
+                    {
+                        ToBytes(array.GetValue(i), bytes, ref numBytes);
+                    }
+                }
+                else
+                {
+                    ToBytes(property.GetValue(sourceClass, null), bytes, ref numBytes);
+                }
+            }
+            return bytes;
+        }
+    }
+}

+ 63 - 0
PLCLinker/snap7Enc/Types/Counter.cs

@@ -0,0 +1,63 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Counter from S7 plc to C# ushort (UInt16).
+    /// </summary>
+    public static class Counter
+    {
+        /// <summary>
+        /// Converts a Counter (2 bytes) to ushort (UInt16)
+        /// </summary>
+        public static UInt16 FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 2)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 2 bytes.");
+            }
+            // bytes[0] -> HighByte
+            // bytes[1] -> LowByte
+            return (UInt16)((bytes[0] << 8) | bytes[1]);
+        }
+
+
+        /// <summary>
+        /// Converts a ushort (UInt16) to word (2 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(UInt16 value)
+        {
+            byte[] bytes = new byte[2];
+
+            bytes[0] = (byte)((value << 8) & 0xFF);
+            bytes[1] = (byte)((value) & 0xFF);
+            
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of ushort (UInt16) to an array of bytes
+        /// </summary>
+        public static byte[] ToByteArray(UInt16[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (UInt16 val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of bytes to an array of ushort
+        /// </summary>
+        public static UInt16[] ToArray(byte[] bytes)
+        {
+            UInt16[] values = new UInt16[bytes.Length / 2];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+    }
+}

+ 65 - 0
PLCLinker/snap7Enc/Types/DInt.cs

@@ -0,0 +1,65 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert DInt from S7 plc to C# int (Int32).
+    /// </summary>
+    public static class DInt
+    {
+        /// <summary>
+        /// Converts a S7 DInt (4 bytes) to int (Int32)
+        /// </summary>
+        public static Int32 FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 4)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
+            }
+            return bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3];
+        }
+
+
+        /// <summary>
+        /// Converts a int (Int32) to S7 DInt (4 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(Int32 value)
+        {
+            byte[] bytes = new byte[4];
+
+            bytes[0] = (byte)((value >> 24) & 0xFF);
+            bytes[1] = (byte)((value >> 16) & 0xFF);
+            bytes[2] = (byte)((value >> 8) & 0xFF);
+            bytes[3] = (byte)((value) & 0xFF);
+
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of int (Int32) to an array of bytes
+        /// </summary>
+        public static byte[] ToByteArray(Int32[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (Int32 val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of S7 DInt to an array of int (Int32)
+        /// </summary>
+        public static Int32[] ToArray(byte[] bytes)
+        {
+            Int32[] values = new Int32[bytes.Length / 4];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+        
+
+    }
+}

+ 73 - 0
PLCLinker/snap7Enc/Types/DWord.cs

@@ -0,0 +1,73 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert DWord from S7 plc to C#.
+    /// </summary>
+    public static class DWord
+    {
+        /// <summary>
+        /// Converts a S7 DWord (4 bytes) to uint (UInt32)
+        /// </summary>
+        public static UInt32 FromByteArray(byte[] bytes)
+        {
+            return (UInt32)(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]);
+        }
+
+
+        /// <summary>
+        /// Converts 4 bytes to DWord (UInt32)
+        /// </summary>
+        public static UInt32 FromBytes(byte b1, byte b2, byte b3, byte b4)
+        {
+            return (UInt32)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
+        }
+
+
+        /// <summary>
+        /// Converts a uint (UInt32) to S7 DWord (4 bytes) 
+        /// </summary>
+        public static byte[] ToByteArray(UInt32 value)
+        {
+            byte[] bytes = new byte[4];
+
+            bytes[0] = (byte)((value >> 24) & 0xFF);
+            bytes[1] = (byte)((value >> 16) & 0xFF);
+            bytes[2] = (byte)((value >> 8) & 0xFF);
+            bytes[3] = (byte)((value) & 0xFF);
+
+            return bytes;
+        }
+
+
+
+
+
+
+        /// <summary>
+        /// Converts an array of uint (UInt32) to an array of S7 DWord (4 bytes) 
+        /// </summary>
+        public static byte[] ToByteArray(UInt32[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (UInt32 val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of S7 DWord to an array of uint (UInt32)
+        /// </summary>
+        public static UInt32[] ToArray(byte[] bytes)
+        {
+            UInt32[] values = new UInt32[bytes.Length / 4];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+    }
+}

+ 91 - 0
PLCLinker/snap7Enc/Types/DataItem.cs

@@ -0,0 +1,91 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Create an instance of a memory block that can be read by using ReadMultipleVars
+    /// </summary>
+    public class DataItem
+    {
+        /// <summary>
+        /// Memory area to read 
+        /// </summary>
+        public DataType DataType { get; set; }
+
+        /// <summary>
+        /// Type of data to be read (default is bytes)
+        /// </summary>
+        public VarType VarType { get; set; }
+
+        /// <summary>
+        /// Address of memory area to read (example: for DB1 this value is 1, for T45 this value is 45)
+        /// </summary>
+        public int DB { get; set; }
+
+        /// <summary>
+        /// Address of the first byte to read
+        /// </summary>
+        public int StartByteAdr { get; set; }
+
+        /// <summary>
+        /// Addess of bit to read from StartByteAdr
+        /// </summary>
+        public byte BitAdr { get; set; }
+
+        /// <summary>
+        /// Number of variables to read
+        /// </summary>
+        public int Count { get; set; }
+
+        /// <summary>
+        /// Contains the value of the memory area after the read has been executed
+        /// </summary>
+        public object Value { get; set; }
+
+        /// <summary>
+        /// Create an instance of DataItem
+        /// </summary>
+        public DataItem()
+        {
+            VarType = VarType.Byte;
+            Count = 1;
+        }
+
+        /// <summary>
+        /// Create an instance of <see cref="DataItem"/> from the supplied address.
+        /// </summary>
+        /// <param name="address">The address to create the DataItem for.</param>
+        /// <returns>A new <see cref="DataItem"/> instance with properties parsed from <paramref name="address"/>.</returns>
+        /// <remarks>The <see cref="Count" /> property is not parsed from the address.</remarks>
+        public static DataItem FromAddress(string address)
+        {
+            PLCAddress.Parse(address, out var dataType, out var dbNumber, out var varType, out var startByte,
+                out var bitNumber);
+
+            return new DataItem
+            {
+                DataType = dataType,
+                DB = dbNumber,
+                VarType = varType,
+                StartByteAdr = startByte,
+                BitAdr = (byte) (bitNumber == -1 ? 0 : bitNumber)
+            };
+        }
+
+        /// <summary>
+        /// Create an instance of <see cref="DataItem"/> from the supplied address and value.
+        /// </summary>
+        /// <param name="address">The address to create the DataItem for.</param>
+        /// <param name="value">The value to be applied to the DataItem.</param>
+        /// <returns>A new <see cref="DataItem"/> instance with properties parsed from <paramref name="address"/> and the supplied value set.</returns>
+        public static DataItem FromAddressAndValue<T>(string address, T value)
+        {
+            var dataItem = FromAddress(address);
+            dataItem.Value = value;
+
+            if (typeof(T).IsArray) dataItem.Count = ((Array) dataItem.Value).Length;
+
+            return dataItem;
+        }
+    }
+}

+ 91 - 0
PLCLinker/snap7Enc/Types/Double.cs

@@ -0,0 +1,91 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Real from S7 plc to C# double.
+    /// </summary>
+    public static class Double
+    {
+        /// <summary>
+        /// Converts a S7 Real (4 bytes) to double
+        /// </summary>
+        public static double FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 4)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
+            }
+
+            // sps uses bigending so we have to reverse if platform needs
+            if (BitConverter.IsLittleEndian)
+            {
+                // create deep copy of the array and reverse
+                bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
+            }
+
+            return BitConverter.ToSingle(bytes, 0);
+        }
+
+        /// <summary>
+        /// Converts a S7 DInt to double
+        /// </summary>
+        public static double FromDWord(Int32 value)
+        {
+            byte[] b = DInt.ToByteArray(value);
+            double d = FromByteArray(b);
+            return d;
+        }
+
+        /// <summary>
+        /// Converts a S7 DWord to double
+        /// </summary>
+        public static double FromDWord(UInt32 value)
+        {
+            byte[] b = DWord.ToByteArray(value);
+            double d = FromByteArray(b);
+            return d;
+        }
+
+
+        /// <summary>
+        /// Converts a double to S7 Real (4 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(double value)
+        {
+            byte[] bytes = BitConverter.GetBytes((float)(value));
+
+            // sps uses bigending so we have to check if platform is same
+            if (!BitConverter.IsLittleEndian) return bytes;
+            
+            // create deep copy of the array and reverse
+            return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
+        }
+
+        /// <summary>
+        /// Converts an array of double to an array of bytes 
+        /// </summary>
+        public static byte[] ToByteArray(double[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (double val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of S7 Real to an array of double
+        /// </summary>
+        public static double[] ToArray(byte[] bytes)
+        {
+            double[] values = new double[bytes.Length / 4];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+        
+    }
+}

+ 87 - 0
PLCLinker/snap7Enc/Types/Int.cs

@@ -0,0 +1,87 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Int from S7 plc to C#.
+    /// </summary>
+    public static class Int
+    {
+        /// <summary>
+        /// Converts a S7 Int (2 bytes) to short (Int16)
+        /// </summary>
+        public static short FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 2)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 2 bytes.");
+            }
+            // bytes[0] -> HighByte
+            // bytes[1] -> LowByte
+            return (short)((int)(bytes[1]) | ((int)(bytes[0]) << 8));
+        }
+
+
+        /// <summary>
+        /// Converts a short (Int16) to a S7 Int byte array (2 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(Int16 value)
+        {
+            byte[] bytes = new byte[2];
+
+            bytes[0] = (byte) (value >> 8 & 0xFF);
+            bytes[1] = (byte)(value & 0xFF);
+
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of short (Int16) to a S7 Int byte array (2 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(Int16[] value)
+        {
+            byte[] bytes = new byte[value.Length * 2];
+            int bytesPos = 0;
+
+            for(int i=0; i< value.Length; i++)
+            {
+                bytes[bytesPos++] = (byte)((value[i] >> 8) & 0xFF);
+                bytes[bytesPos++] = (byte) (value[i] & 0xFF);
+            }
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of S7 Int to an array of short (Int16)
+        /// </summary>
+        public static Int16[] ToArray(byte[] bytes)
+        {
+            int shortsCount = bytes.Length / 2;
+
+            Int16[] values = new Int16[shortsCount];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < shortsCount; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+        
+        /// <summary>
+        /// Converts a C# int value to a C# short value, to be used as word.
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static Int16 CWord(int value)
+        {
+            if (value > 32767)
+            {
+                value -= 32768;
+                value = 32768 - value;
+                value *= -1;
+            }
+            return (short)value;
+        }
+
+    }
+}

+ 91 - 0
PLCLinker/snap7Enc/Types/Single.cs

@@ -0,0 +1,91 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Real from S7 plc to C# float.
+    /// </summary>
+    public static class Single
+    {
+        /// <summary>
+        /// Converts a S7 Real (4 bytes) to float
+        /// </summary>
+        public static float FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 4)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 4 bytes.");
+            }
+
+            // sps uses bigending so we have to reverse if platform needs
+            if (BitConverter.IsLittleEndian)
+            {
+                // create deep copy of the array and reverse
+                bytes = new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
+            }
+
+            return BitConverter.ToSingle(bytes, 0);
+        }
+
+        /// <summary>
+        /// Converts a S7 DInt to float
+        /// </summary>
+        public static float FromDWord(Int32 value)
+        {
+            byte[] b = DInt.ToByteArray(value);
+            float d = FromByteArray(b);
+            return d;
+        }
+
+        /// <summary>
+        /// Converts a S7 DWord to float
+        /// </summary>
+        public static float FromDWord(UInt32 value)
+        {
+            byte[] b = DWord.ToByteArray(value);
+            float d = FromByteArray(b);
+            return d;
+        }
+
+
+        /// <summary>
+        /// Converts a double to S7 Real (4 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(float value)
+        {
+            byte[] bytes = BitConverter.GetBytes((float)(value));
+
+            // sps uses bigending so we have to check if platform is same
+            if (!BitConverter.IsLittleEndian) return bytes;
+            
+            // create deep copy of the array and reverse
+            return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
+        }
+
+        /// <summary>
+        /// Converts an array of float to an array of bytes 
+        /// </summary>
+        public static byte[] ToByteArray(float[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (float val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of S7 Real to an array of float
+        /// </summary>
+        public static float[] ToArray(byte[] bytes)
+        {
+            float[] values = new float[bytes.Length / 4];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+        
+    }
+}

+ 37 - 0
PLCLinker/snap7Enc/Types/String.cs

@@ -0,0 +1,37 @@
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the methods to convert from S7 strings to C# strings
+    /// </summary>
+    public class String
+    {
+        /// <summary>
+        /// Converts a string to <paramref name="reservedLength"/> of bytes, padded with 0-bytes if required.
+        /// </summary>
+        /// <param name="value">The string to write to the PLC.</param>
+        /// <param name="reservedLength">The amount of bytes reserved for the <paramref name="value"/> in the PLC.</param>
+        public static byte[] ToByteArray(string value, int reservedLength)
+        {
+            var length = value?.Length;
+            if (length > reservedLength) length = reservedLength;
+            var bytes = new byte[reservedLength];
+
+            if (length == null || length == 0) return bytes;
+
+            System.Text.Encoding.ASCII.GetBytes(value, 0, length.Value, bytes, 0);
+
+            return bytes;
+        }
+        
+        /// <summary>
+        /// Converts S7 bytes to a string
+        /// </summary>
+        /// <param name="bytes"></param>
+        /// <returns></returns>
+        public static string FromByteArray(byte[] bytes)
+        {
+            return System.Text.Encoding.ASCII.GetString(bytes);
+        }
+
+    }
+}

+ 50 - 0
PLCLinker/snap7Enc/Types/StringEx.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Text;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the methods to convert from S7 strings to C# strings
+    ///   there are two kinds how strings a send. This one is with a pre of two bytes
+    ///   they contain the length of the string
+    /// </summary>
+    public static class StringEx
+    {
+        /// <summary>
+        /// Converts S7 bytes to a string
+        /// </summary>
+        /// <param name="bytes"></param>
+        /// <returns></returns>
+        public static string FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length < 2) return "";
+
+            int size = bytes[0];
+            int length = bytes[1];
+
+            return System.Text.Encoding.ASCII.GetString(bytes, 2, length);
+        }
+
+        /// <summary>
+        /// Converts a <see cref="T:string"/> to S7 string with 2-byte header.
+        /// </summary>
+        /// <param name="value">The string to convert to byte array.</param>
+        /// <param name="reservedLength">The length (in bytes) allocated in PLC for string excluding header.</param>
+        /// <returns>A <see cref="T:byte[]" /> containing the string header and string value with a maximum length of <paramref name="reservedLength"/> + 2.</returns>
+        public static byte[] ToByteArray(string value, int reservedLength)
+        {
+            if (reservedLength > byte.MaxValue) throw new ArgumentException($"The maximum string length supported is {byte.MaxValue}.");
+
+            var length = value?.Length;
+            if (length > reservedLength) length = reservedLength;
+
+            var bytes = new byte[(length ?? 0) + 2];
+            bytes[0] = (byte) reservedLength;
+
+            if (value == null) return bytes;
+
+            bytes[1] = (byte) Encoding.ASCII.GetBytes(value, 0, length.Value, bytes, 2);
+            return bytes;
+        }
+    }
+}

+ 271 - 0
PLCLinker/snap7Enc/Types/Struct.cs

@@ -0,0 +1,271 @@
+using System;
+using System.Reflection;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the method to convert a C# struct to S7 data types
+    /// </summary>
+    public static class Struct
+    {
+        /// <summary>
+        /// Gets the size of the struct in bytes.
+        /// </summary>
+        /// <param name="structType">the type of the struct</param>
+        /// <returns>the number of bytes</returns>
+        public static int GetStructSize(Type structType)
+        {
+            double numBytes = 0.0;
+
+            var infos = structType
+            #if NETSTANDARD1_3
+                .GetTypeInfo().DeclaredFields;
+            #else
+                .GetFields();
+            #endif
+
+            foreach (var info in infos)
+            {
+                switch (info.FieldType.Name)
+                {
+                    case "Boolean":
+                        numBytes += 0.125;
+                        break;
+                    case "Byte":
+                        numBytes = Math.Ceiling(numBytes);
+                        numBytes++;
+                        break;
+                    case "Int16":
+                    case "UInt16":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        numBytes += 2;
+                        break;
+                    case "Int32":
+                    case "UInt32":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        numBytes += 4;
+                        break;
+                    case "Single":
+                    case "Double":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        numBytes += 4;
+                        break;
+                    default:
+                        numBytes += GetStructSize(info.FieldType);
+                        break;
+                }
+            }
+            return (int)numBytes;
+        }
+
+        /// <summary>
+        /// Creates a struct of a specified type by an array of bytes.
+        /// </summary>
+        /// <param name="structType">The struct type</param>
+        /// <param name="bytes">The array of bytes</param>
+        /// <returns>The object depending on the struct type or null if fails(array-length != struct-length</returns>
+        public static object FromBytes(Type structType, byte[] bytes)
+        {
+            if (bytes == null)
+                return null;
+
+            if (bytes.Length != GetStructSize(structType))
+                return null;
+
+            // and decode it
+            int bytePos = 0;
+            int bitPos = 0;
+            double numBytes = 0.0;
+            object structValue = Activator.CreateInstance(structType);
+
+
+            var infos = structValue.GetType()
+            #if NETSTANDARD1_3
+                .GetTypeInfo().DeclaredFields;
+            #else
+                .GetFields();
+            #endif
+
+            foreach (var info in infos)
+            {
+                switch (info.FieldType.Name)
+                {
+                    case "Boolean":
+                        // get the value
+                        bytePos = (int)Math.Floor(numBytes);
+                        bitPos = (int)((numBytes - (double)bytePos) / 0.125);
+                        if ((bytes[bytePos] & (int)Math.Pow(2, bitPos)) != 0)
+                            info.SetValue(structValue, true);
+                        else
+                            info.SetValue(structValue, false);
+                        numBytes += 0.125;
+                        break;
+                    case "Byte":
+                        numBytes = Math.Ceiling(numBytes);
+                        info.SetValue(structValue, (byte)(bytes[(int)numBytes]));
+                        numBytes++;
+                        break;
+                    case "Int16":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        ushort source = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
+                        info.SetValue(structValue, source.ConvertToShort());
+                        numBytes += 2;
+                        break;
+                    case "UInt16":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        info.SetValue(structValue, Word.FromBytes(bytes[(int)numBytes + 1],
+                                                                          bytes[(int)numBytes]));
+                        numBytes += 2;
+                        break;
+                    case "Int32":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        uint sourceUInt = DWord.FromBytes(bytes[(int)numBytes + 3],
+                                                                           bytes[(int)numBytes + 2],
+                                                                           bytes[(int)numBytes + 1],
+                                                                           bytes[(int)numBytes + 0]);
+                        info.SetValue(structValue, sourceUInt.ConvertToInt());
+                        numBytes += 4;
+                        break;
+                    case "UInt32":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        info.SetValue(structValue, DWord.FromBytes(bytes[(int)numBytes],
+                                                                           bytes[(int)numBytes + 1],
+                                                                           bytes[(int)numBytes + 2],
+                                                                           bytes[(int)numBytes + 3]));
+                        numBytes += 4;
+                        break;
+                    case "Double":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        info.SetValue(structValue, Double.FromByteArray(new byte[] { bytes[(int)numBytes],
+                                                                           bytes[(int)numBytes + 1],
+                                                                           bytes[(int)numBytes + 2],
+                                                                           bytes[(int)numBytes + 3] }));
+                        numBytes += 4;
+                        break;
+                    case "Single":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        // hier auswerten
+                        info.SetValue(structValue, Single.FromByteArray(new byte[] { bytes[(int)numBytes],
+                                                                           bytes[(int)numBytes + 1],
+                                                                           bytes[(int)numBytes + 2],
+                                                                           bytes[(int)numBytes + 3] }));
+                        numBytes += 4;
+                        break;
+                    default:
+                        var buffer = new byte[GetStructSize(info.FieldType)];
+                        if (buffer.Length == 0)
+                            continue;
+                        Buffer.BlockCopy(bytes, (int)Math.Ceiling(numBytes), buffer, 0, buffer.Length);
+                        info.SetValue(structValue, FromBytes(info.FieldType, buffer));
+                        numBytes += buffer.Length;
+                        break;
+                }
+            }
+            return structValue;
+        }
+
+        /// <summary>
+        /// Creates a byte array depending on the struct type.
+        /// </summary>
+        /// <param name="structValue">The struct object</param>
+        /// <returns>A byte array or null if fails.</returns>
+        public static byte[] ToBytes(object structValue)
+        {
+            Type type = structValue.GetType();
+
+            int size = Struct.GetStructSize(type);
+            byte[] bytes = new byte[size];
+            byte[] bytes2 = null;
+
+            int bytePos = 0;
+            int bitPos = 0;
+            double numBytes = 0.0;
+
+            var infos = type
+            #if NETSTANDARD1_3
+                .GetTypeInfo().DeclaredFields;
+            #else
+                .GetFields();
+            #endif
+
+            foreach (var info in infos)
+            {
+                bytes2 = null;
+                switch (info.FieldType.Name)
+                {
+                    case "Boolean":
+                        // get the value
+                        bytePos = (int)Math.Floor(numBytes);
+                        bitPos = (int)((numBytes - (double)bytePos) / 0.125);
+                        if ((bool)info.GetValue(structValue))
+                            bytes[bytePos] |= (byte)Math.Pow(2, bitPos);            // is true
+                        else
+                            bytes[bytePos] &= (byte)(~(byte)Math.Pow(2, bitPos));   // is false
+                        numBytes += 0.125;
+                        break;
+                    case "Byte":
+                        numBytes = (int)Math.Ceiling(numBytes);
+                        bytePos = (int)numBytes;
+                        bytes[bytePos] = (byte)info.GetValue(structValue);
+                        numBytes++;
+                        break;
+                    case "Int16":
+                        bytes2 = Int.ToByteArray((Int16)info.GetValue(structValue));
+                        break;
+                    case "UInt16":
+                        bytes2 = Word.ToByteArray((UInt16)info.GetValue(structValue));
+                        break;
+                    case "Int32":
+                        bytes2 = DInt.ToByteArray((Int32)info.GetValue(structValue));
+                        break;
+                    case "UInt32":
+                        bytes2 = DWord.ToByteArray((UInt32)info.GetValue(structValue));
+                        break;
+                    case "Double":
+                        bytes2 = Double.ToByteArray((double)info.GetValue(structValue));
+                        break;
+                    case "Single":
+                        bytes2 = Single.ToByteArray((float)info.GetValue(structValue));
+                        break;
+                }
+                if (bytes2 != null)
+                {
+                    // add them
+                    numBytes = Math.Ceiling(numBytes);
+                    if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                        numBytes++;
+                    bytePos = (int)numBytes;
+                    for (int bCnt = 0; bCnt < bytes2.Length; bCnt++)
+                        bytes[bytePos + bCnt] = bytes2[bCnt];
+                    numBytes += bytes2.Length;
+                }
+            }
+            return bytes;
+        }
+
+
+    }
+}

+ 82 - 0
PLCLinker/snap7Enc/Types/Timer.cs

@@ -0,0 +1,82 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Converts the Timer data type to C# data type
+    /// </summary>
+    public static class Timer
+    {
+        /// <summary>
+        /// Converts the timer bytes to a double
+        /// </summary>
+        public static double FromByteArray(byte[] bytes)
+        {
+            double wert = 0;
+
+            wert = ((bytes[0]) & 0x0F) * 100.0;
+            wert += ((bytes[1] >> 4) & 0x0F) * 10.0;
+            wert += ((bytes[1]) & 0x0F) * 1.0;
+
+            // this value is not used... may for a nother exponation
+            //int unknown = (bytes[0] >> 6) & 0x03;
+
+            switch ((bytes[0] >> 4) & 0x03)
+            {
+                case 0:
+                    wert *= 0.01;
+                    break;
+                case 1:
+                    wert *= 0.1;
+                    break;
+                case 2:
+                    wert *= 1.0;
+                    break;
+                case 3:
+                    wert *= 10.0;
+                    break;
+            }
+
+            return wert;
+        }
+
+        /// <summary>
+        /// Converts a ushort (UInt16) to an array of bytes formatted as time
+        /// </summary>
+        public static byte[] ToByteArray(UInt16 value)
+        {
+            byte[] bytes = new byte[2];
+            bytes[1] = (byte)((int)value & 0xFF);
+            bytes[0] = (byte)((int)value >> 8 & 0xFF);
+
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of ushorts (Uint16) to an array of bytes formatted as time
+        /// </summary>
+        public static byte[] ToByteArray(UInt16[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (UInt16 val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of bytes formatted as time to an array of doubles
+        /// </summary>
+        /// <param name="bytes"></param>
+        /// <returns></returns>
+        public static double[] ToArray(byte[] bytes)
+        {
+            double[] values = new double[bytes.Length / 2];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
+                values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
+
+            return values;
+        }
+    }
+}

+ 71 - 0
PLCLinker/snap7Enc/Types/Word.cs

@@ -0,0 +1,71 @@
+using System;
+
+namespace snap7Enc.Types
+{
+    /// <summary>
+    /// Contains the conversion methods to convert Words from S7 plc to C#.
+    /// </summary>
+    public static class Word
+    {
+        /// <summary>
+        /// Converts a word (2 bytes) to ushort (UInt16)
+        /// </summary>
+        public static UInt16 FromByteArray(byte[] bytes)
+        {
+            if (bytes.Length != 2)
+            {
+                throw new ArgumentException("Wrong number of bytes. Bytes array must contain 2 bytes.");
+            }
+
+            return (UInt16)((bytes[0] << 8) | bytes[1]);
+        }
+
+
+        /// <summary>
+        /// Converts 2 bytes to ushort (UInt16)
+        /// </summary>
+        public static UInt16 FromBytes(byte b1, byte b2)
+        {
+            return (UInt16)((b2 << 8) | b1);
+        }
+
+
+        /// <summary>
+        /// Converts a ushort (UInt16) to word (2 bytes)
+        /// </summary>
+        public static byte[] ToByteArray(UInt16 value)
+        {
+            byte[] bytes = new byte[2];
+
+            bytes[1] = (byte)(value & 0xFF);
+            bytes[0] = (byte)((value>>8) & 0xFF);
+
+            return bytes;
+        }
+
+        /// <summary>
+        /// Converts an array of ushort (UInt16) to an array of bytes
+        /// </summary>
+        public static byte[] ToByteArray(UInt16[] value)
+        {
+            ByteArray arr = new ByteArray();
+            foreach (UInt16 val in value)
+                arr.Add(ToByteArray(val));
+            return arr.Array;
+        }
+
+        /// <summary>
+        /// Converts an array of bytes to an array of ushort
+        /// </summary>
+        public static UInt16[] ToArray(byte[] bytes)
+        {
+            UInt16[] values = new UInt16[bytes.Length/2];
+
+            int counter = 0;
+            for (int cnt = 0; cnt < bytes.Length/2; cnt++)
+                values[cnt] = FromByteArray(new byte[] {bytes[counter++], bytes[counter++]});
+
+            return values;
+        }
+    }
+}

+ 71 - 0
PLCLinker/snap7Enc/snap7Enc.csproj

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{C1364CBB-83D7-44C7-B982-5A09F7EC1AC0}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>snap7Enc</RootNamespace>
+    <AssemblyName>snap7Enc</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Plc.cs" />
+    <Compile Include="Conversion.cs" />
+    <Compile Include="Enums.cs" />
+    <Compile Include="PLCAddress.cs" />
+    <Compile Include="PlcException.cs" />
+    <Compile Include="PLCExceptions.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Sharp7.cs" />
+    <Compile Include="Types\Bit.cs" />
+    <Compile Include="Types\Boolean.cs" />
+    <Compile Include="Types\Byte.cs" />
+    <Compile Include="Types\ByteArray.cs" />
+    <Compile Include="Types\Class.cs" />
+    <Compile Include="Types\Counter.cs" />
+    <Compile Include="Types\DataItem.cs" />
+    <Compile Include="Types\DInt.cs" />
+    <Compile Include="Types\Double.cs" />
+    <Compile Include="Types\DWord.cs" />
+    <Compile Include="Types\Int.cs" />
+    <Compile Include="Types\Single.cs" />
+    <Compile Include="Types\String.cs" />
+    <Compile Include="Types\StringEx.cs" />
+    <Compile Include="Types\Struct.cs" />
+    <Compile Include="Types\Timer.cs" />
+    <Compile Include="Types\Word.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>