//#define _TEST_BASIC_VAR #define _TEST_PLCTAG using System; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using S7CommPlusDriver; using S7CommPlusDriver.ClientApi; namespace DriverTest { class Program { static void Main(string[] args) { string HostIp = "192.168.0.250"; string Password = ""; int res; List readlist = new List(); Console.WriteLine("Main - START"); // Als Parameter lässt sich die IP-Adresse übergeben, sonst Default-Wert von oben if (args.Length >= 1) { HostIp = args[0]; } // Als Parameter lässt sich das Passwort übergeben, sonst Default-Wert von oben (kein Passwort) if (args.Length >= 2) { Password = args[1]; } Console.WriteLine("Main - Versuche Verbindungsaufbau zu: " + HostIp); S7CommPlusConnection conn = new S7CommPlusConnection(); conn.OnlySecurePGOrPCAndHMI = false; System.Diagnostics.Stopwatch stopwatch1 = new System.Diagnostics.Stopwatch(); stopwatch1.Start(); res = conn.Connect(HostIp, Password); stopwatch1.Stop(); byte[] var1_crc_bytes = { 0x88, 0xdd, 0xa4, 0x83, 0x34 }; Console.WriteLine($"PLCType: {conn.PLCInformation.PLCType} | MLFB: {conn.PLCInformation.MLFB} | Firmware: {conn.PLCInformation.Firmware}"); Console.WriteLine($"连接耗时{stopwatch1.ElapsedMilliseconds}ms."); if (res == 0) { Console.WriteLine("按任意键浏览变量"); Console.ReadKey(); Console.WriteLine("Main - Connect fertig"); #region Variablenhaushalt browsen Console.WriteLine("Main - Starte Browse..."); // Variablenhaushalt auslesen List vars = new List(); res = conn.Browse(out vars); Console.WriteLine("Main - Browse res=" + res); #endregion List vars_ = vars.GetRange(0, 1000); #if _TEST_PLCTAG #region Werte aller Variablen einlesen Console.WriteLine("Main - Lese Werte aller Variablen aus"); List taglist = new List(); foreach (var v in vars_) { ItemAddress itemAddress = new ItemAddress(v.AccessSequence); //S7p.DecodeUInt32Vlq(new MemoryStream(var1_crc_bytes), out itemAddress.SymbolCrc); taglist.Add(PlcTags.TagFactory(v.Name, itemAddress, v.Softdatatype)); } if (res == 0) { Console.WriteLine("====================== VARIABLENHAUSHALT ======================"); string formatstring = "{0,-80}{1,-30}{2,-20}{3,-20}"; Console.WriteLine(String.Format(formatstring, "SYMBOLIC-NAME", "ACCESS-SEQUENCE", "TYP", "QC: VALUE")); for (int i = 0; i < vars_.Count; i++) { string s; s = String.Format(formatstring, taglist[i].Name, taglist[i].Address.GetAccessString(), Softdatatype.Types[taglist[i].Datatype], taglist[i].ToString()); Console.WriteLine(s); } } #endregion Console.WriteLine("按任意键开始读或订阅"); Console.ReadKey(); res = conn.SubscriptionCreate(taglist, 100); if (res == 0) { Task.Run(() => { conn.TestWaitForVariableChangeNotifications(50000000000); }); } while (res == 0) { System.Diagnostics.Stopwatch stopwatch2 = new System.Diagnostics.Stopwatch(); stopwatch2.Start(); res = PlcTags.ReadTags(conn, taglist); stopwatch2.Stop(); long ms = stopwatch2.ElapsedMilliseconds; if (res == 0) { string header = $"读取{vars_.Count}个变量耗时{ms}毫秒"; Console.WriteLine(header); } //System.Threading.Thread.Sleep(50); } #endif #if _TEST_BASIC_VAR #region Werte aller Variablen einlesen Console.WriteLine("Main - Lese Werte aller Variablen aus"); foreach (var v in vars) { readlist.Add(new ItemAddress(v.AccessSequence)); } List values = new List(); List errors = new List(); // Fehlerhafte Variable setzen //readlist[2].LID[0] = 123; res = conn.ReadValues(readlist, out values, out errors); #endregion #region Variablenhaushalt mit Werten ausgeben if (res == 0) { Console.WriteLine("====================== VARIABLENHAUSHALT ======================"); // Liste ausgeben string formatstring = "{0,-80}{1,-30}{2,-20}{3,-20}"; Console.WriteLine(String.Format(formatstring, "SYMBOLIC-NAME", "ACCESS-SEQUENCE", "TYP", "VALUE")); for (int i = 0; i < vars.Count; i++) { string s = String.Format(formatstring, vars[i].Name, vars[i].AccessSequence, Softdatatype.Types[vars[i].Softdatatype], values[i]); Console.WriteLine(s); } Console.WriteLine("==============================================================="); } #endregion #endif /* #region Test: Wert schreiben List writevalues = new List(); PValue writeValue = new ValueInt(8888); writevalues.Add(writeValue); List writelist = new List(); writelist.Add(new ItemAddress("8A0E0001.F")); errors.Clear(); res = conn.WriteValues(writelist, writevalues, out errors); Console.WriteLine("res=" + res); #endregion */ /* #region Test: Absolutadressen lesen // Daten aus nicht "optimierten" Datenbausteinen lesen readlist.Clear(); ItemAddress absAdr = new ItemAddress(); absAdr.SetAccessAreaToDatablock(100); // DB 100 absAdr.SymbolCrc = 0; absAdr.AccessSubArea = Ids.DB_ValueActual; absAdr.LID.Add(3); // LID_OMS_STB_ClassicBlob absAdr.LID.Add(0); // Blob Start Offset, Anfangsadresse absAdr.LID.Add(20); // 20 Bytes readlist.Add(absAdr); values.Clear(); errors.Clear(); res = conn.ReadValues(readlist, out values, out errors); Console.WriteLine(values.ToString()); #endregion */ #region Test: SPS in Stopp setzen Console.WriteLine("Setze SPS in STOP..."); conn.SetPlcOperatingState(1); Console.WriteLine("Taste drücken um wieder in RUN zu setzen..."); Console.ReadKey(); Console.WriteLine("Setze SPS in RUN..."); conn.SetPlcOperatingState(3); #endregion conn.Disconnect(); } else { Console.WriteLine("Main - Connect fehlgeschlagen!"); } Console.WriteLine("Main - ENDE. Bitte Taste drücken."); Console.ReadKey(); } } public static class S7SymbolCrc32 { private const uint Polynomial = 0xFA567993; // 多项式(x³² + x³¹ + x³⁰ + x²⁹ + x²⁸ + x²⁶ + x²³ + x²¹ + x¹⁹ + x¹⁸ + x¹⁵ + x¹⁴ + x¹³ + x¹² + x⁹ + x⁸ + x⁴ + x + 1) private const uint InitialValue = 0xFFFFFFFF; private static readonly uint[] Table; static S7SymbolCrc32() { // 预计算CRC表 Table = new uint[256]; for (uint i = 0; i < 256; i++) { uint crc = i << 24; for (int j = 0; j < 8; j++) { if ((crc & 0x80000000) != 0) { crc = (crc << 1) ^ Polynomial; } else { crc <<= 1; } } Table[i] = crc; } } /// /// 计算S7CommPlus符号名的CRC32校验和 /// /// 符号名(如"DB1.TempBottom") /// 数据类型字节 /// CRC32校验和 public static uint CalculateSymbolCrc(string symbolName) { // 1. 替换分隔符 '.' → 0x09 string processedName = symbolName.Replace('.', '\t'); // 2. 转换为字节数组 byte[] nameBytes = Encoding.ASCII.GetBytes(processedName); // 3. 添加数据类型字节 byte[] data = new byte[nameBytes.Length]; Array.Copy(nameBytes, 0, data, 0, nameBytes.Length); // 4. 计算CRC32 uint crc = InitialValue; foreach (byte b in data) { crc = (crc << 8) ^ Table[((crc >> 24) & 0xFF) ^ b]; } // 5. 根据作者提示,可能需要再次计算(需要验证) //crc = CalculateSecondPass(crc); return crc; } // 如果需要二次计算的方法 public static uint CalculateSecondPass(uint firstResult) { byte[] crcBytes = BitConverter.GetBytes(firstResult); if (BitConverter.IsLittleEndian) { Array.Reverse(crcBytes); // 确保大端序 } uint crc = InitialValue; foreach (byte b in crcBytes) { crc = (crc << 8) ^ Table[((crc >> 24) & 0xFF) ^ b]; } return crc; } } }