SiemensPLCService.cs
6.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using AutomaticGrooveCalculationTool.DataAccess;
using AutomaticGrooveCalculationTool.Model;
using Microsoft.EntityFrameworkCore;
using S7.Net;
using S7.Net.Types;
using System.Text;
using System.Text.RegularExpressions;
namespace AutomaticGrooveCalculationTool.Services
{
public class SiemensPLCService
{
public readonly List<Plc> Plcs;
public readonly List<Equipment> Equipments;
private readonly ILogger<SiemensPLCService> _logger;
private readonly IDbContextFactory<DataContext> _dbContextFactory;
public SiemensPLCService(ILogger<SiemensPLCService> logger, IDbContextFactory<DataContext> dbContextFactory)
{
using var context = dbContextFactory.CreateDbContext();
var result = context.Database.EnsureCreated();
Equipments = context.Equipment.ToList();
Plcs = Equipments.DistinctBy(x => x.IP).Select(x => new Plc(x.CpuType, x.IP, 0, x.CpuType switch
{
CpuType.S7300 or CpuType.S7400 => 2,
_ => 0
})).ToList();
_logger = logger;
_dbContextFactory = dbContextFactory;
}
/// <summary>
/// 读取PLC数据
/// </summary>
/// <param name="equipmentProps"></param>
/// <remarks><see cref="EquipmentProp"/>需要关联设备</remarks>
public void Read(IEnumerable<EquipmentProp> equipmentProps)
{
const int limit = 10;
foreach (var item in equipmentProps.GroupBy(x => x.Equipment.IP))
{
var plc = Plcs.Find(x => x.IP == item.Key) ?? throw new Exception($"未找到IP为{item.Key}的Plc对象");
for (int i = 0; i < item.Count(); i += limit)
{
var readItems = item.Skip(i).Take(limit).Select(ConvertToDataItem).ToList();
plc.ReadMultipleVars(readItems);
foreach (var dataItem in readItems)
{
var index = readItems.IndexOf(dataItem);
readItems[index].Value = dataItem.Value?.ToString() ?? string.Empty;
}
}
}
}
/// <summary>
/// 将数据写入PLC
/// </summary>
/// <param name="equipmentProps"></param>
/// <remarks><see cref="EquipmentProp"/>需要关联设备</remarks>
public void Write(IEnumerable<EquipmentProp> equipmentProps)
{
const int limit = 10;
foreach (var item in equipmentProps.GroupBy(x => x.Equipment.IP))
{
var plc = Plcs.Find(x => x.IP == item.Key) ?? throw new Exception($"未找到IP为{item.Key}的Plc对象");
for (int i = 0; i < item.Count(); i += limit)
{
var writeItems = item.Skip(i).Take(limit).ToList();
plc.Write(writeItems.Select(ConvertToDataItem).ToArray());
}
}
}
private DataItem ConvertToDataItem(EquipmentProp equipmentProp)
{
DataType dataType;
if (equipmentProp.Address.StartsWith("I", StringComparison.OrdinalIgnoreCase))
{
dataType = DataType.Input;
}
else if (equipmentProp.Address.StartsWith("O", StringComparison.OrdinalIgnoreCase))
{
dataType = DataType.Output;
}
else if (equipmentProp.Address.StartsWith("M", StringComparison.OrdinalIgnoreCase))
{
dataType = DataType.Memory;
}
else if (equipmentProp.Address.StartsWith("DB", StringComparison.OrdinalIgnoreCase))
{
dataType = DataType.DataBlock;
}
else if (equipmentProp.Address.StartsWith("T", StringComparison.OrdinalIgnoreCase))
{
dataType = DataType.Timer;
}
else
{
throw new Exception($"Id:{equipmentProp.Id}地址{equipmentProp.Address}地址格式不正确!");
}
var regex = new Regex("[0-9]+");
var stringArray = equipmentProp.Address.Split('.');
_ = int.TryParse(regex.Match(stringArray[0]).Value, out int db);
int startByteAdr = 0;
byte bitAdr = 0;
if (stringArray.Length == 2)
{
_ = int.TryParse(regex.Match(stringArray[1]).Value, out startByteAdr);
}
else if (stringArray.Length == 3)
{
_ = int.TryParse(regex.Match(stringArray[1]).Value, out startByteAdr);
_ = byte.TryParse(regex.Match(stringArray[2]).Value, out bitAdr);
}
else if (stringArray.Length > 3)
{
throw new Exception($"属性Id为“{equipmentProp.Id}”的{nameof(equipmentProp.Address)}格式不正确!");
}
return new DataItem
{
DataType = dataType,
VarType = equipmentProp.VarType,
DB = db,
BitAdr = bitAdr,
Count = 1,
StartByteAdr = startByteAdr,
Value = equipmentProp.VarType switch
{
VarType.Bit => Convert.ToBoolean(equipmentProp.Value),
VarType.Byte => Encoding.Default.GetBytes(equipmentProp.Value),
VarType.Word => Convert.ToUInt16(equipmentProp.Value),
VarType.DWord => Convert.ToUInt32(equipmentProp.Value),
VarType.Int => Convert.ToInt16(equipmentProp.Value),
VarType.DInt => Convert.ToInt32(equipmentProp.Value),
VarType.Real => Convert.ToSingle(equipmentProp.Value),
VarType.LReal => Convert.ToDouble(equipmentProp.Value),
VarType.String => equipmentProp.Value,
VarType.S7String => throw new NotImplementedException(),
VarType.S7WString => throw new NotImplementedException(),
VarType.Timer => throw new NotImplementedException(),
VarType.Counter => throw new NotImplementedException(),
VarType.DateTime or VarType.DateTimeLong => Convert.ToDateTime(equipmentProp.Value),
_ => throw new NotImplementedException(),
},
};
}
}
}