using HH.WCS.JuShi.api;
|
using HH.WCS.JuShi.util;
|
using Microsoft.Owin.BuilderProperties;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Linq;
|
using S7.Net;
|
using S7.Net.Types;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Data.SqlTypes;
|
using System.Linq;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using System.Web.Services.Description;
|
using static HH.WCS.JuShi.util.Settings;
|
|
namespace HH.WCS.JuShi.device
|
{
|
|
/// <summary>
|
/// 西门子plc
|
/// </summary>
|
public class S7Helper
|
{
|
private static bool debug = true;
|
private static byte[] Ssxbytes = new byte[0];
|
private static S7.Net.Plc plc = null;
|
static S7Helper()
|
{
|
Init();
|
}
|
private static Dictionary<string, Plc> plcDic = new Dictionary<string, Plc>();
|
private static void Init()
|
{
|
//配置文件读取所有的plc进行初始化
|
try
|
{
|
var plc1 = new Plc(CpuType.S71500, "", 0, 1);
|
plcDic.Add("plc1", plc1);
|
Link(plc1);
|
}
|
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<string, string> s7TestData = new Dictionary<string, string>();
|
private 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
|
|
|
|
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)
|
{
|
result = (short[])plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, count, 0);
|
Console.WriteLine($"读取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}");
|
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;
|
}
|
|
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="db"></param>
|
/// <param name="byteAddr"></param>
|
/// <param name="data"></param>
|
/// <returns></returns>
|
internal static bool WriteInt(int db, int byteAddr, short data)
|
{
|
var result = false;
|
try
|
{
|
var linkplc = Settings.SafeInteractions.First();
|
var plc = new Plc(CpuType.S71200, linkplc.ip, 0, 1);
|
Link(plc);
|
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} ");
|
if (result)
|
{
|
//写完再读一次确认
|
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)}", "PLC");
|
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 object ReadBit(string device, int db, int byteAddr, byte bitAddr)
|
{
|
object result = null;
|
try
|
{
|
if (debug)
|
{
|
var s7Key = $"bit_{db}_{byteAddr}_{bitAddr}";
|
if (s7TestData.ContainsKey(s7Key))
|
{
|
var data = s7TestData[s7Key];
|
if (data == "1")
|
{
|
result = true;
|
}
|
else { result = false; }
|
Console.WriteLine($"读取plc {device}信息成功, addr={byteAddr} data={result.ToString()}");
|
}
|
}
|
else
|
{
|
var plc = GetPlc(device);
|
if (plc != null)
|
{
|
if (plc.IsConnected)
|
{
|
result = plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, bitAddr);
|
Console.WriteLine($"读取plc {device}信息成功,ip={plc.IP} addr={byteAddr} data={result.ToString()}");
|
}
|
else
|
{
|
Console.WriteLine($"准备连接plc {device}");
|
Link(plc);
|
}
|
}
|
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
|
{
|
if (plc.IsConnected)
|
{
|
result = plc.Read(DataType.DataBlock, 100, byteAddr, VarType.String, count, 0).ToString();
|
Console.WriteLine($"ReadStr 成功,ip={plc.IP} addr={byteAddr} res={result}");
|
if (result.Length == 0)
|
{
|
Link(plc);
|
}
|
}
|
else
|
{
|
Console.WriteLine("准备连接plc");
|
Link(plc);
|
}
|
}
|
}
|
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;
|
}
|
|
|
public static PlcDeviceTable plcDeviceTables = new PlcDeviceTable();
|
/// <summary>
|
/// 获取输送线数据
|
/// </summary>
|
public static void ReadSsxPLc()
|
{
|
var db = new SqlHelper<WCSTask>().GetInstance();
|
try
|
{
|
var linkplc = Settings.linePlcInfos.Find(a => a.enable == 1);
|
var plc = new Plc(CpuType.S71500, linkplc.address, 0, 1);
|
Link(plc);
|
//拆托机
|
//object rawValue = plc.Read(DataType.DataBlock, 8, 230, VarType.Byte, 1);
|
//LogHelper.Info($"Raw value: {rawValue} (Type: {rawValue?.GetType()})");
|
// 先读取整个字节
|
byte data = (byte)plc.Read(DataType.DataBlock, 8, 230, VarType.Byte, 1);
|
// 然后提取各个位
|
bool requestPut1 = (data & 0x01) != 0; // 230.0 1001
|
bool requestTake1 = (data & 0x02) != 0; // 230.1 1003
|
bool requestPut2 = (data & 0x04) != 0; // 230.2 1004
|
bool requestTake2 = (data & 0x08) != 0; // 230.3 1006
|
LogHelper.Info($"拆托机接收信号====={requestPut1},{requestTake1},{requestPut2},{requestTake2}");
|
|
//RGV
|
// RGV允许卸货状态读取 (从DB51读取)
|
int rgv1AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 0, VarType.Int, 1);
|
int rgv2AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 2, VarType.Int, 1);
|
int rgv3AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 4, VarType.Int, 1);
|
int rgv4AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 6, VarType.Int, 1);
|
int rgv5AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 8, VarType.Int, 1);
|
int rgv6AllowUnload = (int)plc.Read(DataType.DataBlock, 51, 10, VarType.Int, 1);
|
LogHelper.Info($"RGV接收信号=== 1={rgv1AllowUnload}, 2={rgv2AllowUnload}, 3={rgv3AllowUnload}, 4={rgv4AllowUnload}, 5={rgv5AllowUnload}, 6={rgv6AllowUnload}");
|
|
//存到缓存
|
if (plcDeviceTables != null)
|
{
|
plcDeviceTables.requestTake1 = requestTake1;
|
plcDeviceTables.requestPut1 = requestPut1;
|
plcDeviceTables.requestTake2 = requestTake2;
|
plcDeviceTables.requestPut2 = requestPut2;
|
plcDeviceTables.RGVAllowUnload = new Dictionary<int, int>
|
{
|
{1, rgv1AllowUnload},
|
{2, rgv2AllowUnload},
|
{3, rgv3AllowUnload},
|
{4, rgv4AllowUnload},
|
{5, rgv5AllowUnload},
|
{6, rgv6AllowUnload}
|
};
|
LogHelper.Info($"S7协议第一次读取参数:{JsonConvert.SerializeObject(plcDeviceTables)}");
|
}
|
else
|
{
|
var plcDeviceTable = new PlcDeviceTable();
|
plcDeviceTable.requestTake1 = requestTake1;
|
plcDeviceTable.requestPut1 = requestPut1;
|
plcDeviceTable.requestTake2 = requestTake2;
|
plcDeviceTable.requestPut2 = requestPut2;
|
plcDeviceTable.RGVAllowUnload = new Dictionary<int, int>
|
{
|
{1, rgv1AllowUnload},
|
{2, rgv2AllowUnload},
|
{3, rgv3AllowUnload},
|
{4, rgv4AllowUnload},
|
{5, rgv5AllowUnload},
|
{6, rgv6AllowUnload}
|
};
|
plcDeviceTables = plcDeviceTable;
|
LogHelper.Info($"S7协议读取参数:{JsonConvert.SerializeObject(plcDeviceTable)}");
|
}
|
|
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine("ReadSsxPLc:" + ex.Message + ex.StackTrace);
|
LogHelper.Error("ReadSsxPLc:" + ex.Message, ex);
|
throw;
|
}
|
|
|
}
|
///// <summary>
|
///// 获取输送线数据
|
///// </summary>
|
//public static void oldReadSsxPLc()
|
//{
|
// //#region 测试写入数据
|
// //List<S7Model> s7Models = new List<S7Model>();
|
// //s7Models.Add(new S7Model() { addr = 0, value = "1", type = "Int", length = 2 });
|
// //s7Models.Add(new S7Model() { addr = 2, value = "2", type = "Int", length = 2 });
|
// //s7Models.Add(new S7Model() { addr = 4, value = "4", type = "Int", length = 2 });
|
// //s7Models.Add(new S7Model() { addr = 18, value = "TP24121108", type = "String", length = 20 });
|
// //var plcInfo = Settings.linePlcInfo.Where(a => (a.deviceNo == "2") && a.enable == 1).FirstOrDefault();
|
// //Write(s7Models, 100, plcInfo);
|
// //#endregion
|
|
// var db = new SqlHelper<WCSTask>().GetInstance();
|
// try
|
// {
|
// //两个拆托机
|
// var linkplcs = Settings.linePlcInfos.FindAll(a => a.enable == 1).ToList();
|
// foreach (var linkplc in linkplcs)
|
// {
|
// //获取设备配置文件
|
// var deviceInfos = Settings.ConveyorLinesInfos.Where(a => a.enable == 1 && a.deviceNo == linkplc.deviceNo).ToList();
|
// if (deviceInfos.Count > 0)
|
// {
|
// int slen = int.Parse(deviceInfos.Min(a => a.readAddr).ToString());
|
// int elen = int.Parse(deviceInfos.Max(a => a.readAddr).ToString());
|
|
// //读取输送线整个偏移量的byte数组 放内存里一起解析,防止过度读取
|
// //PLCRead(linkplc.address, 8, slen, elen + 18, out Ssxbytes);
|
|
// var plc = new Plc(CpuType.S71500, linkplc.address, 0, 1);
|
// Link(plc);
|
// //一个拆托机两个线体
|
// foreach (var device in deviceInfos)
|
// {
|
// //int workMode = int.Parse(GetValue(int.Parse(device.readAddr.ToString()), VarType.Int, Ssxbytes)); //工作模式
|
// //int lightAction = int.Parse(GetValue(int.Parse((device.readAddr + 2).ToString()), VarType.Int, Ssxbytes)); //是否有货,光电信号
|
|
// //int workMode = (short)plc.Read(DataType.DataBlock, 8, int.Parse(device.readAddr.ToString()), VarType.Int, 1, 0);
|
// //int lightAction = (short)plc.Read(DataType.DataBlock, 8, int.Parse((device.readAddr + 2).ToString()), VarType.Int, 1, 0);
|
|
// int requestTake1 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 0);
|
// int requestPut1 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 1);
|
// int requestTake2 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 2);
|
// int requestPut2 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 3);
|
|
// LogHelper.Info($"readbool2================={requestTake1},{requestPut1},{requestTake2},{requestPut2}");
|
// //var requestTake = plc.Read("DB8.DBX" + device.readAddr + 16.0);//输送线请求取框
|
// //var requestPut = plc.Read("DB8.DBX" + device.readAddr + 16.1);//输送线允许放框
|
|
// //存到缓存
|
// //var task = plcDeviceTables.Find(a => a.DeviceNo == device.code);
|
// if (task != null)
|
// {
|
// task.DeviceNo = device.code;
|
// //task.workMode = workMode;
|
// //task.lightAction = lightAction;
|
// task.requestTake1 = requestTake1;
|
// task.requestPut1 = requestPut1;
|
// task.requestTake2 = requestTake2;
|
// task.requestPut2 = requestPut2;
|
// LogHelper.Info($"S7协议第一次读取参数:{JsonConvert.SerializeObject(task)}");
|
// }
|
// else
|
// {
|
// var plcDeviceTable = new PlcDeviceTable();
|
// plcDeviceTable.DeviceNo = device.code;
|
// //plcDeviceTable.workMode = workMode;
|
// //plcDeviceTable.lightAction = lightAction;
|
// plcDeviceTable.requestTake1 = requestTake1;
|
// plcDeviceTable.requestPut1 = requestPut1;
|
// plcDeviceTable.requestTake2 = requestTake2;
|
// plcDeviceTable.requestPut2 = requestPut2;
|
// plcDeviceTables.Add(plcDeviceTable);
|
// LogHelper.Info($"S7协议读取参数:{JsonConvert.SerializeObject(plcDeviceTable)}");
|
// }
|
|
// }
|
// }
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// Console.WriteLine("ReadSsxPLc:" + ex.Message + ex.StackTrace);
|
// LogHelper.Error("ReadSsxPLc:" + ex.Message, ex);
|
// throw;
|
// }
|
|
|
//}
|
///// <summary>
|
///// 批量写入方法
|
///// </summary>
|
///// <param name="writemodels">写入list</param>
|
///// <param name="readdb">写入db</param>
|
///// <param name="plcInfo">配置文件</param>
|
//public static void Write(List<S7Model> writemodels, int readdb, LinePlcInfo plcInfo)
|
//{
|
// // var plcInfo = Settings.linePlcInfo.Where(a => (a.deviceNo == "2") && a.enable == 1).FirstOrDefault();
|
|
// //获取配置文件写入的地址
|
// //List<S7Model> writemodels = Settings.plcValue.Find(a => a.address == plcInfo.address).read;
|
|
// if (writemodels.Count > 0)
|
// {
|
|
// byte[] bytes = GetWriteByte(writemodels);
|
// if (PLCWrite(plcInfo, readdb, bytes))
|
// {
|
// Console.WriteLine("写入成功");
|
// //写入成功校验数据
|
// //Read();
|
// //if (Dictvalues[plcInfo.address].Find(a => a.addr == 2).value == "2")
|
// //{
|
// // Console.WriteLine("数据校验成功,修改任务状态");
|
// //}
|
// }
|
// else
|
// {
|
// Console.WriteLine("写入失败");
|
// }
|
// }
|
// // int taskNo = 12100001;
|
// //写入byte数据,杭叉堆垛机默认从偏移量6开始 6,8,10为起点排列层 12 14 16终点排列层 18任务类型以此类推,具体写入byte根据文档调整
|
// // byte[] bytes = new byte[30] {
|
// //0,(byte)int.Parse("2"),
|
// //0,(byte)int.Parse("3"),
|
// //0,(byte)int.Parse("4"),
|
// //0,(byte)int.Parse("5"),
|
// //0,(byte)int.Parse("6"),
|
// //0,(byte)int.Parse("7"),
|
// //0,(byte)1,
|
// //0,1,
|
// //0,0,
|
// //0,0,
|
// //0,0,
|
// //0,0,
|
// //0,0,
|
// //(byte)((uint)(taskNo >> 24) & 0xFFu),
|
// //(byte)((uint)(taskNo >> 16) & 0xFFu),
|
// //(byte)((uint)(taskNo >> 8) & 0xFFu),
|
// //(byte)((uint)taskNo & 0xFFu)
|
// //};
|
// //byte[] bytes = new byte[4] {
|
// // 0,(byte)int.Parse("2"),
|
// //0,(byte)int.Parse("3")
|
|
// //};
|
|
//}
|
|
|
///// <summary>
|
///// S7写入byte数组
|
///// </summary>
|
///// <param name="plcInfo">配置文件</param>
|
///// <param name="db">DB块</param>
|
///// <param name="bytes"></param>
|
///// <returns></returns>
|
//public static bool PLCWrite(Settings.LinePlcInfo plcInfo, int db, byte[] bytes)
|
//{
|
// bool result = false;
|
// var plc = new Plc(CpuType.S71500, plcInfo.address, 0, 1);
|
// Link(plc);
|
|
// try
|
// {
|
// result = plc.WriteBytes(DataType.DataBlock, Convert.ToInt16(db), Convert.ToInt16(plcInfo.writeAddr), bytes) == ErrorCode.NoError;
|
|
// return result;
|
// }
|
// catch (Exception ex)
|
// {
|
|
// throw ex;
|
// }
|
|
//}
|
/// <summary>
|
/// 将要写的数据转换成byte
|
/// </summary>
|
/// <param name="writemodels"></param>
|
/// <returns></returns>
|
public static byte[] GetWriteByte(List<S7Model> writemodels)
|
{
|
var model = writemodels.OrderByDescending(a => a.addr).First();
|
var readlen = model.addr + model.length;
|
byte[] bytes = new byte[readlen];
|
|
foreach (var item in writemodels)
|
{
|
if (!string.IsNullOrEmpty(item.value))
|
{
|
//转换byte
|
switch (item.type)
|
{
|
case "Int":
|
case "Bit":
|
bytes[item.addr] = (byte)((uint)(int.Parse(item.value) >> 8) & 0xFFu);
|
bytes[item.addr + 1] = (byte)((uint)(int.Parse(item.value) >> 0) & 0xFFu);
|
break;
|
case "DInt":
|
case "Real":
|
bytes[item.addr] = (byte)((uint)(int.Parse(item.value) >> 24) & 0xFFu);
|
bytes[item.addr + 1] = (byte)((uint)(int.Parse(item.value) >> 16) & 0xFFu);
|
bytes[item.addr + 2] = (byte)((uint)(int.Parse(item.value) >> 8) & 0xFFu);
|
bytes[item.addr + 3] = (byte)((uint)(int.Parse(item.value) >> 0) & 0xFFu);
|
break;
|
case "String":
|
case "Byte":
|
var bytevalue = Encoding.UTF8.GetBytes(item.value);
|
if (bytevalue.Count() <= item.length)
|
{
|
for (int i = 0; i < bytevalue.Count(); i++)
|
{
|
|
bytes[item.addr + item.length - bytevalue.Count() + i] = bytevalue[i];
|
}
|
}
|
break;
|
}
|
}
|
|
}
|
return bytes;
|
}
|
/// <summary>
|
/// S7读取byte数组
|
/// </summary>
|
/// <param name="address">地址</param>
|
/// <param name="db">DB块</param>
|
/// <param name="addr">读取起始偏移量</param>
|
/// <param name="bytes">输出byte</param>
|
/// <returns></returns>
|
public static bool PLCRead(string address, int db, int addr, int len, out byte[] bytes)
|
{
|
|
bool result = false;
|
var plc = new Plc(CpuType.S71500, address, 0, 1);
|
Link(plc);
|
|
string res = string.Empty;
|
bytes = new byte[len];
|
try
|
{
|
bytes = plc.ReadBytes(DataType.DataBlock, Convert.ToInt16(db), Convert.ToInt16(addr), len);
|
var r1 = "new byte[] {" + string.Join(",", bytes) + " }";
|
res = $" B{db} A{addr} L{len} A{r1}";
|
}
|
catch (Exception ex)
|
{
|
res = "Err" + ex.Message + ex.StackTrace;
|
}
|
|
// result = plc.WriteBytes(DataType.DataBlock, Convert.ToInt16(1000), Convert.ToInt16(linePlcInfo.writeAddr + 6), bytes) == ErrorCode.NoError;
|
return result;
|
}
|
|
/// <summary>
|
/// 解析
|
/// </summary>
|
/// <param name="adr"></param>
|
/// <param name="varType"></param>
|
/// <param name="d"></param>
|
/// <param name="length"></param>
|
/// <returns></returns>
|
public static string GetValue(int adr, VarType varType, byte[] d, int length = 1)
|
{
|
//计算类型长度,string类型为可变长度用配置文件定义的长度
|
var vlen = VarTypeToByteLength(varType);
|
if (varType == VarType.String)
|
{
|
vlen = length;
|
}
|
|
if (adr + vlen > d.Length)
|
{
|
return "";
|
}
|
|
var adrbyte = d.Skip(adr).Take(vlen).ToArray();
|
if (varType == VarType.String)
|
{
|
adrbyte = adrbyte.Skip(adrbyte.ToList().FindIndex(x => x > 0)).ToArray();
|
}
|
|
var obj = ParseBytes(varType, adrbyte, 1, 0);
|
return obj.ToString();
|
|
}
|
private static int VarTypeToByteLength(VarType varType, int varCount = 1)
|
{
|
switch (varType)
|
{
|
case VarType.Bit:
|
return varCount;
|
case VarType.Byte:
|
if (varCount >= 1)
|
{
|
return varCount;
|
}
|
|
return 1;
|
case VarType.String:
|
return varCount;
|
|
case VarType.Word:
|
case VarType.Int:
|
case VarType.Timer:
|
case VarType.Counter:
|
return varCount * 2;
|
case VarType.DWord:
|
case VarType.DInt:
|
case VarType.Real:
|
return varCount * 4;
|
default:
|
return 0;
|
}
|
}
|
private static object ParseBytes(VarType varType, byte[] bytes, int varCount, byte bitAdr = 0)
|
{
|
if (bytes == null)
|
{
|
return null;
|
}
|
|
switch (varType)
|
{
|
case VarType.Byte:
|
if (varCount == 1)
|
{
|
return bytes[0];
|
}
|
|
return bytes;
|
case VarType.Word:
|
if (varCount == 1)
|
{
|
return Word.FromByteArray(bytes);
|
}
|
|
return Word.ToArray(bytes);
|
case VarType.Int:
|
if (varCount == 1)
|
{
|
return Int.FromByteArray(bytes);
|
}
|
|
return Int.ToArray(bytes);
|
case VarType.DWord:
|
if (varCount == 1)
|
{
|
return DWord.FromByteArray(bytes);
|
}
|
|
return DWord.ToArray(bytes);
|
case VarType.DInt:
|
if (varCount == 1)
|
{
|
return DInt.FromByteArray(bytes);
|
}
|
|
return DInt.ToArray(bytes);
|
case VarType.Real:
|
if (varCount == 1)
|
{
|
return S7.Net.Types.Double.FromByteArray(bytes);
|
}
|
|
return S7.Net.Types.Double.ToArray(bytes);
|
case VarType.String:
|
return S7.Net.Types.String.FromByteArray(bytes);
|
|
case VarType.Timer:
|
if (varCount == 1)
|
{
|
return S7.Net.Types.Timer.FromByteArray(bytes);
|
}
|
|
return S7.Net.Types.Timer.ToArray(bytes);
|
case VarType.Counter:
|
if (varCount == 1)
|
{
|
return Counter.FromByteArray(bytes);
|
}
|
|
return Counter.ToArray(bytes);
|
case VarType.Bit:
|
if (varCount == 1)
|
{
|
if (bitAdr > 7)
|
{
|
return null;
|
}
|
|
return Bit.FromByte(bytes[0], bitAdr);
|
}
|
|
return Bit.ToBitArray(bytes);
|
default:
|
return null;
|
}
|
}
|
|
internal static bool WriteDouble(string deviceNo, int db, int byteAddr, int offsetAddr, int data)
|
{
|
var result = false;
|
try
|
{
|
var linkplcs = Settings.linePlcInfos.Find(a => a.deviceNo == deviceNo);
|
var plc = new Plc(CpuType.S71500, linkplcs.address, 0, 1);
|
Link(plc);
|
if (plc.IsConnected)
|
{
|
if (byteAddr != 0)
|
{
|
plc.WriteBit(DataType.DataBlock, db, byteAddr, offsetAddr, true);
|
Console.WriteLine($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ");
|
LogHelper.Info($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ");
|
//睡三秒 如果还继续发请求的话就重写入 否则写入false
|
Thread.Sleep(3000);
|
var plcDeviceTable = S7Helper.plcDeviceTables;
|
if (plcDeviceTable != null)
|
{
|
if ((offsetAddr == 0 && plcDeviceTable.requestPut1)
|
|| (offsetAddr == 1 && plcDeviceTable.requestTake1)
|
|| (offsetAddr == 2 && plcDeviceTable.requestPut2)
|
|| (offsetAddr == 3 && plcDeviceTable.requestTake2))
|
{
|
WriteDouble(deviceNo, db, byteAddr, offsetAddr, data);
|
}
|
else
|
{
|
plc.WriteBit(DataType.DataBlock, db, byteAddr, offsetAddr, false);
|
LogHelper.Info($"S7发送复位信号");
|
}
|
|
}
|
|
//if (result)
|
//{
|
// //写完再读一次确认
|
// //var readData = (short)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, 0);
|
|
// //byte data1 = (byte)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Byte, 1);
|
// //// 然后提取各个位
|
// //bool requestPut1 = (data1 & 0x01) != 0; // 230.0 1001
|
|
// var readData = (short)plc.Read("DB9.DBX" + byteAddr);
|
// 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)}", "PLC");
|
// 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 bool WritePlc(int startAddr, int data, Settings.linePlcInfo plcInfo, int dataType = 16)
|
//{
|
// var result = false;
|
// S7.Net.Plc plc = null;
|
// plc = plcInfo.deviceNo == "1" ? plc1 : plcInfo.deviceNo == "3" ? plc3 : null;
|
// string rwAction = "写入";
|
// if (plc != null)
|
// {
|
// try
|
// {
|
// if (plc.IsConnected)
|
// {
|
// //CMMLog.Info($"{rwAction}plc信息-Start,ip={plc.IP} addr={startAddr} data={data}");
|
// var res = new ErrorCode { };
|
// //var res = plc7.Write(DataType.DataBlock, 101, Convert.ToInt16(startAddr),1, (Int16)data);
|
// if (dataType == 16) res = plc.Write(DataType.DataBlock, Convert.ToInt16(1000), Convert.ToInt16(startAddr), Convert.ToInt16(data));
|
// else res = plc.Write(DataType.DataBlock, Convert.ToInt16(1000), Convert.ToInt16(startAddr), Convert.ToInt32(data));
|
// result = (int)res == 0;
|
// //CMMLog.Info($"{rwAction}plc信息-End,ip={plc.IP} addr={startAddr} data={data} res={res}");
|
// }
|
// else
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息-UnLink,ip={plc.IP} addr={startAddr} data={data}");
|
// Link(plc);
|
// //CMMLog.Error($"{rwAction}plc信息-UnLink_ReWrite,ip={plc.IP} addr={startAddr} data={data}");
|
// result = RWriteStackerPlc1(startAddr, data, plcInfo, dataType);
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息失败-Failed,ip={plc.IP} addr={startAddr} data={data} err={ex.Message}");
|
// Link(plc);
|
// }
|
|
// if (!result)
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息失败,重新写入-Failed_ReWrite,ip={plc.IP} addr={startAddr} data={data}");
|
// result = RWriteStackerPlc1(startAddr, data, plcInfo, dataType);
|
// }
|
// }
|
// else CMMLog.Error($"{rwAction}plc信息失败,此设备未进行初始化,配置信息:{JsonConvert.SerializeObject(plcInfo)}");
|
|
// return result;
|
// //}
|
|
//}
|
////单个写入
|
//public static bool WriteStackerPlc1(int startAddr, int data, Settings.linePlcInfo plcInfo, int dataType = 16)
|
//{
|
|
// //lock (WriteStackerPlc1Lock)
|
// //{
|
// var result = false;
|
|
// S7.Net.Plc plc = null;
|
// plc = plcInfo.deviceNo == "1" ? plc1 : plcInfo.deviceNo == "3" ? plc3 : null;
|
// string rwAction = "写入";
|
// if (plc != null)
|
// {
|
// try
|
// {
|
// if (plc.IsConnected)
|
// {
|
// //CMMLog.Info($"{rwAction}plc信息-Start,ip={plc.IP} addr={startAddr} data={data}");
|
// var res = new ErrorCode { };
|
// //var res = plc7.Write(DataType.DataBlock, 101, Convert.ToInt16(startAddr),1, (Int16)data);
|
// if (dataType == 16) res = plc.Write(DataType.DataBlock, Convert.ToInt16(1000), Convert.ToInt16(startAddr), Convert.ToInt16(data));
|
// else res = plc.Write(DataType.DataBlock, Convert.ToInt16(1000), Convert.ToInt16(startAddr), Convert.ToInt32(data));
|
// result = (int)res == 0;
|
// //CMMLog.Info($"{rwAction}plc信息-End,ip={plc.IP} addr={startAddr} data={data} res={res}");
|
// }
|
// else
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息-UnLink,ip={plc.IP} addr={startAddr} data={data}");
|
// Link(plc);
|
// //CMMLog.Error($"{rwAction}plc信息-UnLink_ReWrite,ip={plc.IP} addr={startAddr} data={data}");
|
// result = RWriteStackerPlc1(startAddr, data, plcInfo, dataType);
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息失败-Failed,ip={plc.IP} addr={startAddr} data={data} err={ex.Message}");
|
// Link(plc);
|
// }
|
|
// if (!result)
|
// {
|
// //CMMLog.Error($"{rwAction}plc信息失败,重新写入-Failed_ReWrite,ip={plc.IP} addr={startAddr} data={data}");
|
// result = RWriteStackerPlc1(startAddr, data, plcInfo, dataType);
|
// }
|
// }
|
// else CMMLog.Error($"{rwAction}plc信息失败,此设备未进行初始化,配置信息:{JsonConvert.SerializeObject(plcInfo)}");
|
|
// return result;
|
// //}
|
|
//}
|
/// <summary>
|
/// 批量写入model
|
/// </summary>
|
public class S7Model
|
{
|
/// <summary>
|
/// 偏移量
|
/// </summary>
|
public int addr { get; set; }
|
/// <summary>
|
/// 类型
|
/// </summary>
|
public string type { get; set; }
|
/// <summary>
|
/// 长度
|
/// </summary>
|
public int length { get; set; }
|
/// <summary>
|
/// 值
|
/// </summary>
|
public string value { get; set; }
|
}
|
|
//S7写入信号 测试用
|
internal static Results S7Write(int offsetAddr)
|
{
|
var linkplcs = Settings.linePlcInfos.Find(a => a.deviceNo == "1");
|
var plc = new Plc(CpuType.S71500, linkplcs.address, 0, 1);
|
Link(plc);
|
plc.WriteBit(DataType.DataBlock, 9, 182, offsetAddr, false);
|
return new Results() { Code = "0", Message = $"写入成功", Data = null };
|
}
|
|
#region 用于模拟测试
|
/// <summary>
|
/// short类型,一个占2个byte
|
/// </summary>
|
public class DBWModel
|
{
|
public int db { get; set; }
|
public int byteAddr { get; set; }
|
/// <summary>
|
/// int类型需要用逗号分开,string不需要
|
/// </summary>
|
public string value { get; set; }
|
}
|
/// <summary>
|
/// 字符串类型,一个占1个byte
|
/// </summary>
|
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; }
|
/// <summary>
|
/// 1:true 0:false
|
/// </summary>
|
public int value { get; set; }
|
}
|
public static void s7SetInt(DBWModel model)
|
{
|
var data = model.value.Replace(",", "");
|
var s7Key = $"int_{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 == 1 ? "1" : "0";
|
if (s7TestData.ContainsKey(s7Key))
|
{
|
s7TestData[s7Key] = value;
|
}
|
else
|
{
|
s7TestData.Add(s7Key, value);
|
}
|
}
|
|
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
|
}
|