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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FLY.Modbus
{
/// <summary>
/// PLC 区管理
/// </summary>
public abstract class AreaManager
{
/// <summary>
/// 现在工作中的读取计划任务
/// </summary>
public List<Plan> plan = new List<Plan>();
/// <summary>
/// 当true, plan_buffer -> plan
/// </summary>
protected bool isPlanChanged = false;
/// <summary>
/// 设置读取计划任务时的缓冲,目前线程安全
/// </summary>
protected List<Plan> plan_buffer = new List<Plan>();
/// <summary>
/// 当前执行的计划任务序号
/// </summary>
protected int currIndex = 0;
/// <summary>
/// 获取下一个plan,返回下一个plan,若已经到了最后一个,则在开始
/// 下一个之前,返回一个null
/// </summary>
/// <returns></returns>
public Plan GetNextPlan()
{
int cnt = plan.Count();
if (cnt <= 0) return null;
if (currIndex >= cnt)
{
currIndex = 0;
return null;
}
Plan p = plan.ElementAt(currIndex);
currIndex += 1;
return p;
}
/// <summary>
/// 清除doing状态
/// </summary>
public void ClearPlanState()
{
foreach (Plan p in plan)
{
p.isDoing = false;
}
currIndex = 0;
}
/// <summary>
/// 一个property 对应 N个 PLC寄存器;
/// 地址必须是从小到大排列,不能有重叠
/// </summary>
public List<DataToRegs> regs = new List<DataToRegs>();
protected PLCAddressArea area;
protected int maxOfOneRead = 50;
public AreaManager(PLCAddressArea area, int maxOfOneRead)
{
this.area = area;
this.maxOfOneRead = maxOfOneRead;
}
/// <summary>
/// 根据DataToRegs列表构建数组
/// </summary>
public void BuildArray(List<DataToRegs> DRmap)
{
List<DataToRegs> drs = DRmap.FindAll((c) =>
{
return c.dataArea == area;
});
// 分配寄存器存储空间
regs.Clear();
foreach (DataToRegs dr in drs)
{
regs.Add(dr);
}
regs.Sort((r1, r2) =>
{
if (r1.addr < r2.addr)
return -1;
else if (r1.addr > r2.addr)
return 1;
else
return 0;
});
}
/// <summary>
///
/// </summary>
public void MakePlanReal()
{
lock (plan_buffer)
{
if (isPlanChanged)
{
isPlanChanged = false;
plan.Clear();
plan.AddRange(plan_buffer);
}
}
}
/// <summary>
/// 根据当前regs的配置指定读寄存器的计划
/// 只是设置 plan_buffer
/// </summary>
public abstract void MakePlan();
/// <summary>
/// 从本地PC 属性获取value 更新到 本地PLC 寄存器,
/// 目的: 当从PLC读取寄存器值时,能比较不同,产生变化事件
/// </summary>
public void SetAllIsPlcValueChanged()
{
foreach (DataToRegs dr in regs)
{
dr.isPlcValueChanged = true;
}
}
}
/// <summary>
/// 每次向PLC读取寄存器的任务
/// </summary>
public class Plan
{
/// <summary>
/// coil or register
/// </summary>
public PLCAddressArea area;
/// <summary>
/// 地址
/// </summary>
public int addr;
/// <summary>
/// 数量
/// </summary>
public int num;
/// <summary>
/// 是否正在读取
/// </summary>
public bool isDoing;
/// <summary>
///
/// </summary>
/// <param name="area"></param>
/// <param name="addr"></param>
/// <param name="num"></param>
public Plan(PLCAddressArea area, int addr, int num)
{
this.area = area;
this.addr = addr;
this.num = num;
}
}
}