using HH.WCS.Mobox3.HD.api; using HH.WCS.Mobox3.HD.util; using Newtonsoft.Json.Linq; using S7.Net; using S7.Net.Types; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Web.Services.Description; namespace HH.WCS.Mobox3.HD.device { /// /// 西门子plc /// public class S7Helper { private static bool debug = false; private static S7.Net.Plc plc = null; static S7Helper() { Init(); } internal static Dictionary plcDic = new Dictionary(); // 堆垛机 public static void Init() { //配置文件读取所有的plc进行初始化 try { foreach (var item in Settings.devicePlcInfos) { var plc = new Plc(CpuType.S71500, item.address, 0, 1); Link(plc); plcDic.Add(item.deviceNo, plc); } } catch (Exception ex) { Console.WriteLine("S7Helper Init err=" + ex.Message); } } private static Plc GetPlc(string plc) { if (plcDic.ContainsKey(plc)) { return plcDic[plc]; } else { return null; } } public static Dictionary s7TestData = new Dictionary(); public static void Link(Plc plc) { try { if (!plc.IsConnected) { plc.Close(); plc.Open(); if (plc.IsConnected) { Console.WriteLine($"已连接到plc{plc.IP}"); } else { Console.WriteLine($"plc{plc.IP}连接失败"); LogHelper.Info($"plc{plc.IP}连接失败", "Plc"); } } } catch (Exception ex) { Console.WriteLine($"plc{plc.IP}连接失败,err={ex.Message}"); LogHelper.Info($"plc{plc.IP}连接失败,err={ex.Message}"); //Init(); } } //https://www.ad.siemens.com.cn/productportal/Prods/S7-1200_PLC_EASY_PLUS/SmartSMS/060.html //https://www.ad.siemens.com.cn/productportal/Prods/S7-1200_PLC_EASY_PLUS/07-Program/02-basic/01-Data_Type/09-String.html /// /// 从指定的西门子PLC设备中读取整数数据。 /// /// PLC设备的标识符或名称。 /// 要读取的数据块的编号。 /// 在数据块中的起始字节地址。--偏移量 /// 要读取的整数数量。-- 长度 /// 包含读取到的整数数据的数组。如果发生错误或未读取到数据,则返回null。 internal static short[] ReadInt(string device, int db, int byteAddr, int count) { short[] result = null; try { if (debug) { var s7Key = $"int_{db}_{byteAddr}_{count}"; if (s7TestData.ContainsKey(s7Key)) { var data = s7TestData[s7Key].Split(','); if (data.Length == count) { result = Array.ConvertAll(data, s => short.Parse(s)); } else { result = new short[count]; s7TestData[s7Key] = string.Join(",", result); } Console.WriteLine($"读取plc {device}信息成功, addr={byteAddr} data={string.Join(",", result)}"); } } else { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { LogHelper.Info($"开始读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} count={count}", "哈电"); result = (short[])plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, count, 0); LogHelper.Info($"读取成功plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}","哈电"); if (result.Length == 0) { Console.WriteLine($"plc {device}准备重新连接"); Link(plc); } } } else { LogHelper.Info($"plc {device}不存在", "哈电"); } } } catch (Exception ex) { Console.WriteLine($"ReadInt,device={device} addr={byteAddr} count={count} err={ex.Message}"); LogHelper.Error($"ReadInt,device={device} addr={byteAddr} count={count} err={ex.Message}", ex); } return result; } /// /// 从指定的西门子PLC设备中读取整数数据。 /// /// PLC设备的标识符或名称。 /// 要读取的数据块的编号。 /// 在数据块中的起始字节地址。--偏移量 /// 要读取的整数数量。-- 长度 /// 包含读取到的整数数据的数组。如果发生错误或未读取到数据,则返回null。 internal static short ReadInt(string device, int db, int byteAddr) { short result = -1; try { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { LogHelper.Info($"开始读取plc {device}信息成功,ip={plc.IP} addr={byteAddr}", "哈电"); result = (short)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, 0); LogHelper.Info($"读取成功plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}", "哈电"); } } else { LogHelper.Info($"plc {device}不存在", "哈电"); } } catch (Exception ex) { Console.WriteLine($"ReadInt,device={device} addr={byteAddr} err={ex.Message}"); LogHelper.Error($"ReadInt,device={device} addr={byteAddr} err={ex.Message}", ex); } return result; } /// /// 从指定的西门子PLC设备中读取整数数据。 /// /// PLC设备的标识符或名称。 /// 要读取的数据块的编号。 /// 在数据块中的起始字节地址。--偏移量 /// 要读取的整数数量。-- 长度 /// 包含读取到的整数数据的数组。如果发生错误或未读取到数据,则返回null。 internal static int[] ReadDint(string device, int db, int byteAddr, int count) { int[] result = null; try { if (debug) { var s7Key = $"Dint_{db}_{byteAddr}_{count}"; if (s7TestData.ContainsKey(s7Key)) { var data = s7TestData[s7Key].Split(','); if (data.Length == count) { result = Array.ConvertAll(data, s => int.Parse(s)); } else { result = new int[count]; s7TestData[s7Key] = string.Join(",", result); } Console.WriteLine($"读取plc {device}信息成功, addr={byteAddr} data={string.Join(",", result)}"); } } else { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { LogHelper.Info($"开始读取plc {device}信息,ip={plc.IP} addr={byteAddr} count={count}", "哈电"); result = (int[])plc.Read(DataType.DataBlock, db, byteAddr, VarType.DInt, count, 0); Console.WriteLine($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}"); LogHelper.Info($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}","哈电"); if (result.Length == 0) { Console.WriteLine($"plc {device}准备重新连接"); Link(plc); } } } else { Console.WriteLine($"plc {device}不存在"); } } } catch (Exception ex) { Console.WriteLine($"ReadInt,device={device} addr={byteAddr} count={count} err={ex.Message}"); LogHelper.Error($"ReadInt,device={device} addr={byteAddr} count={count} err={ex.Message}", ex); } return result; } /// /// 从指定的西门子PLC设备中读取整数数据。 /// /// PLC设备的标识符或名称。 /// 要读取的数据块的编号。 /// 在数据块中的起始字节地址。--偏移量 /// 要读取的整数数量。-- 长度 /// 包含读取到的整数数据的数组。如果发生错误或未读取到数据,则返回null。 internal static int ReadDint(string device, int db, int byteAddr) { int result = 0; try { if (debug) { var s7Key = $"Dint_{db}_{byteAddr}_{1}"; if (s7TestData.ContainsKey(s7Key)) { string str = s7TestData[s7Key]; result = int.Parse(str); Console.WriteLine($"读取plc {device}信息成功, addr={byteAddr} data={string.Join(",", result)}"); } } else { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { result = (int)plc.Read(DataType.DataBlock, db, byteAddr, VarType.DInt, 1, 0); Console.WriteLine($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}"); LogHelper.Info($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={string.Join(",", result)}", "哈电"); } } else { Console.WriteLine($"plc {device}不存在"); } } } catch (Exception ex) { Console.WriteLine($"ReadInt,device={device} addr={byteAddr} count={1} err={ex.Message}"); LogHelper.Error($"ReadInt,device={device} addr={byteAddr} count={1} err={ex.Message}", ex); } return result; } /// /// /// /// /// /// /// /// internal static bool WriteInt(string device, int db, int byteAddr, short data) { var result = false; try { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { plc.Write(DataType.DataBlock, db, byteAddr, data); Console.WriteLine($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} "); LogHelper.Info($"写入plc {device}信息,ip={plc.IP} addr={byteAddr} data={data} ", "哈电"); //写完再读一次确认 var readData = (short)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, 0); Console.WriteLine($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}"); LogHelper.Info($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}", "哈电"); result = readData == data; } else { Console.WriteLine("准备连接plc"); Link(plc); } } } catch (Exception ex) { LogHelper.Error($"写入plc1信息失败,ip={plc.IP} addr={byteAddr} data={data} err={ex.Message}", ex); } return result; } /// /// /// /// /// /// /// /// internal static bool WriteDint(string device,int db, int byteAddr, int data) { var result = false; try { var plc = GetPlc(device); if (plc.IsConnected) { plc.Write(DataType.DataBlock, db, byteAddr, data); Console.WriteLine($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} "); LogHelper.Info($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ", "哈电"); //写完再读一次确认 var readData = (int)plc.Read(DataType.DataBlock, db, byteAddr, VarType.DInt, 1, 0); Console.WriteLine($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}"); LogHelper.Info($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}", "哈电"); result = readData == data; } else { Console.WriteLine("准备连接plc1"); Link(plc); } } catch (Exception ex) { LogHelper.Error($"写入plc1信息失败,ip={plc.IP} addr={byteAddr} data={data} err={ex.Message}", ex); } return result; } /// /// /// /// /// /// /// /// internal static bool WriteString(string device, int db, int byteAddr, string data) { var result = false; try { var plc = GetPlc(device); if (plc.IsConnected) { plc.Write(DataType.DataBlock, db, byteAddr, data); Console.WriteLine($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} "); LogHelper.Info($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ", "哈电"); //写完再读一次确认 var readData = (string)plc.Read(DataType.DataBlock, db, byteAddr, VarType.String, 1, 0); Console.WriteLine($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}"); LogHelper.Info($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}", "哈电"); result = readData == data; } else { Console.WriteLine("准备连接plc1"); Link(plc); } } catch (Exception ex) { LogHelper.Error($"写入plc1信息失败,ip={plc.IP} addr={byteAddr} data={data} err={ex.Message}", ex); } return result; } public static byte ReadBit(string device, int db, int byteAddr, byte bitAddr) { byte result = 0; try { if (debug) { var s7Key = $"bit_{db}_{byteAddr}_{bitAddr}"; if (s7TestData.ContainsKey(s7Key)) { var data = s7TestData[s7Key]; result = byte.Parse(data); Console.WriteLine($"读取plc {device}信息成功, addr={byteAddr} data={result.ToString()}"); } } else { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { result = (byte)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Byte, 1); Console.WriteLine($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={result.ToString()}"); } } else { Console.WriteLine($"plc {device}不存在"); } } } catch (Exception ex) { Console.WriteLine($"ReadBit,device={device} addr={byteAddr} bit={bitAddr} err={ex.Message}"); LogHelper.Error($"ReadBit,device={device} addr={byteAddr} bit={bitAddr} err={ex.Message}", ex); } return result; } public static string ReadStr(string device, int db, int byteAddr, int count) { string result = string.Empty; try { if (debug) { var s7Key = $"str_{db}_{byteAddr}_{count}"; if (s7TestData.ContainsKey(s7Key)) { var data = s7TestData[s7Key]; if (data.Length == count) { result = data; Console.WriteLine($"ReadStr 成功, addr={byteAddr} res={result}"); } } } else { var plc = GetPlc(device); if (plc != null) { if (plc.IsConnected) { result = Convert.ToString(plc.Read(DataType.DataBlock, db, byteAddr, VarType.String, count)); Console.WriteLine($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={result}"); LogHelper.Info($"读取plc {device}信息,ip={plc.IP} addr={byteAddr} data={result} ","哈电"); } } } } catch (Exception ex) { Console.WriteLine($"ReadStr,device={device} addr={byteAddr} count={count} err={ex.Message}"); LogHelper.Error($"ReadStr,device={device} addr={byteAddr} count={count} err={ex.Message}", ex); } return result; } #region 用于模拟测试 /// /// short类型,一个占2个byte /// public class DBWModel { public int db { get; set; } public int byteAddr { get; set; } /// /// int类型需要用逗号分开,string不需要 /// public string value { get; set; } } /// /// 字符串类型,一个占1个byte /// public class DBBModel { public int db { get; set; } public int byteAddr { get; set; } public string value { get; set; } } public class DBXModel { public int db { get; set; } public int byteAddr { get; set; } public int bitAddr { get; set; } /// /// 1:true 0:false /// public int value { get; set; } } public static void s7SetInt(DBWModel model) { var data = model.value.Split(','); var s7Key = $"int_{model.db}_{model.byteAddr}_{data.Length}"; if (s7TestData.ContainsKey(s7Key)) { s7TestData[s7Key] = model.value; } else { s7TestData.Add(s7Key, model.value); } } public static void s7SetDint(DBWModel model) { var data = model.value.Split(','); var s7Key = $"Dint_{model.db}_{model.byteAddr}_{data.Length}"; if (s7TestData.ContainsKey(s7Key)) { s7TestData[s7Key] = model.value; } else { s7TestData.Add(s7Key, model.value); } } internal static void s7SetBit(DBXModel model) { var s7Key = $"bit_{model.db}_{model.byteAddr}_{model.bitAddr}"; var value = model.value; if (s7TestData.ContainsKey(s7Key)) { s7TestData[s7Key] = value.ToString(); } else { s7TestData.Add(s7Key, value.ToString()); } } internal static void s7SetStr(DBBModel model) { var s7Key = $"str_{model.db}_{model.byteAddr}_{model.value.Length}"; if (s7TestData.ContainsKey(s7Key)) { s7TestData[s7Key] = model.value; } else { s7TestData.Add(s7Key, model.value); } } } #endregion }