Commit 23c17d7b authored by 潘栩锋's avatar 潘栩锋 🚴

完成 ModbusMapper_Client 线程版

parent 7924757b
......@@ -220,7 +220,7 @@ namespace FLY.IBC.Server
foreach (PLCGroup.PLCDevice device in plcgroup.Devices)
{
ModbusMapper_Client plc = new ModbusMapper_Client(new ClientTCP(device.EP));
var plc = new Modbus.WithThread.ModbusMapper_Client(new Modbus.WithThread.ClientTCP(device.EP));
plcos.PLCs.Add(plc);
}
......@@ -233,20 +233,22 @@ namespace FLY.IBC.Server
if (var.DeviceIndex < 0 || var.DeviceIndex >= plcos.PLCs.Count)
continue;
List<ModbusMapper.DataToRegs> drs = plcos.DRMap;
ModbusMapper_Client plc = plcos.PLCs[var.DeviceIndex];
List<Modbus.DataToRegs> drs = plcos.DRMap;
var plc = plcos.PLCs[var.DeviceIndex];
ModbusMapper.DataToRegs dr = plc.MapDataToRegs(
Modbus.DataToRegs dr = plc.MapDataToRegs(
ModbusMapper.TranslateToPLCAddressArea(var.Mode),
var.Addr,
ModbusMapper.TranslateToREG_TYPE(var.Type),
var.Scale,
Item,
var.PropertyName);
if (dr != null)
drs.Add(dr);
}
foreach (var plc in plcos.PLCs)
plc.Build();
}
public void Save()
......
......@@ -7,7 +7,23 @@ namespace FLY.Modbus
{
public abstract class AreaManagerBase
{
/// <summary>
/// 现在工作中的读取计划任务
/// </summary>
protected 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,若已经到了最后一个,则在开始
......@@ -40,7 +56,20 @@ namespace FLY.Modbus
currIndex = 0;
}
/// <summary>
/// 根据DataToRegs列表构建数组
/// </summary>
public abstract void BuildArray(List<DataToRegs> DRmap);
/// <summary>
/// 根据当前regs的配置指定读寄存器的计划
/// 只是设置 plan_buffer
/// </summary>
public abstract void MakePlan();
/// <summary>
/// 把plan_buffer -> plan
/// </summary>
public abstract void MakePlanReal();
}
public abstract class AreaManager<T> : AreaManagerBase
where T : PLCRegObj, new()
......@@ -62,7 +91,7 @@ namespace FLY.Modbus
/// <summary>
/// 根据DataToRegs列表构建数组
/// </summary>
public virtual void BuildArray(List<DataToRegs> DRmap)
public override void BuildArray(List<DataToRegs> DRmap)
{
List<DataToRegs> drs = DRmap.FindAll((c) =>
{
......@@ -87,11 +116,20 @@ namespace FLY.Modbus
});
}
/// <summary>
/// 根据当前regs的配置指定读寄存器的计划
///
/// </summary>
public abstract void MakePlan();
public override void MakePlanReal()
{
lock (plan_buffer)
{
if (isPlanChanged)
{
isPlanChanged = false;
plan.Clear();
plan.AddRange(plan_buffer);
}
}
}
}
/// <summary>
......
......@@ -39,39 +39,45 @@ namespace FLY.Modbus
{
throw new Exception("还没有执行 BuildArray()");
}
plan.Clear();
int addr = -1;
int num = 0;
for (int i = 0; i < regs.Count(); i++)
lock (plan_buffer)
{
if (!regs[i].dr.isNeedUpdate)
continue;
plan_buffer.Clear();
if (addr == -1)
{
addr = regs[i].dr.addr;
num = 1;
}
else
int addr = -1;
int num = 0;
for (int i = 0; i < regs.Count(); i++)
{
int n = regs[i].dr.addr - addr + 1;
if (n <= maxOfOneRead)
if (!regs[i].dr.isNeedUpdate)
continue;
if (addr == -1)
{
num = n;
addr = regs[i].dr.addr;
num = 1;
}
else
{
plan.Add(new Plan(area, addr, num));
addr = -1;
i--;
int n = regs[i].dr.addr - addr + 1;
if (n <= maxOfOneRead)
{
num = n;
}
else
{
plan_buffer.Add(new Plan(area, addr, num));
addr = -1;
i--;
}
}
}
}
if (addr != -1)
{
plan.Add(new Plan(area, addr, num));
addr = -1;
if (addr != -1)
{
plan_buffer.Add(new Plan(area, addr, num));
addr = -1;
}
isPlanChanged = true;
}
}
}
......
......@@ -55,7 +55,6 @@
<Compile Include="DataToRegs.cs" />
<Compile Include="ModbusMapper_Client.cs" />
<Compile Include="IModbusClient.cs" />
<Compile Include="IModbusRegister.cs" />
<Compile Include="ModbusMapper.cs" />
<Compile Include="Pack_Proto.cs" />
<Compile Include="PLCGroup.cs" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FLY.Modbus
{
/// <summary>
/// 读写操作 回调函数
/// </summary>
public interface IModbusRegister
{
/// <summary>
/// 设置Modbus的值,会改变相应命名数据的值,并产生通知
/// </summary>
/// <param name="area">coil or register</param>
/// <param name="addr">地址</param>
/// <param name="val">值,类型为ushort[]或bool[]</param>
/// <returns></returns>
void SetModbusData(PLCAddressArea area, int addr, object val);
/// <summary>
/// 获取Modbus的数据值
/// </summary>
/// <param name="area">coil or register</param>
/// <param name="addr">地址</param>
/// <param name="num">数量</param>
/// <returns>类型为ushort[]或bool[]</returns>
object GetModbusData(PLCAddressArea area, int addr, int num);
}
/// <summary>
/// PLC 地址空间, 线圈 or 寄存器
/// </summary>
public enum PLCAddressArea
{
/// <summary>
/// 线圈
/// </summary>
Coil,
/// <summary>
/// 寄存器
/// </summary>
Register
}
}
......@@ -9,7 +9,7 @@ namespace FLY.Modbus
/// <summary>
/// 命名数据到Modbus数据的映射
/// </summary>
public abstract class ModbusMapper : IModbusRegister, INotifyPropertyChanged
public abstract class ModbusMapper : INotifyPropertyChanged
{
/// <summary>
/// 一次读取的数据量
......@@ -26,17 +26,9 @@ namespace FLY.Modbus
{
NameDataChanged?.Invoke(this, new NameDataChangedEventArgs(dataclass, dataname));
}
public event ModbusDataChangedEventHandler ModbusDataChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyModbusDataChanged(PLCAddressArea dataarea, int addr, int num)
{
ModbusDataChanged?.Invoke(this, new ModbusDataChangedEventArgs(dataarea, addr, num));
}
#endregion
......@@ -47,10 +39,8 @@ namespace FLY.Modbus
public ModbusMapper()
{
registers = new RegisterData(PLCAddressArea.Register, MaxRegsOfOneRead);
coils = new CoilData(PLCAddressArea.Coil, MaxCoilsOfOneRead);
mAreaManager.Add(registers);
mAreaManager.Add(coils);
mAreaManager.Add(new CoilData(PLCAddressArea.Coil, MaxCoilsOfOneRead));
mAreaManager.Add(new RegisterData(PLCAddressArea.Register, MaxRegsOfOneRead));
}
#region 数据映射
......@@ -99,18 +89,9 @@ namespace FLY.Modbus
#endregion
#region Modbus数据
/// <summary>
/// PLC寄存器 对应的 property
/// 就是 coils 与 registers 的组合
/// </summary>
public RegisterData registers;
/// <summary>
/// PLC 继电器 对应的 property
/// </summary>
public CoilData coils;
public List<AreaManagerBase> mAreaManager = new List<AreaManagerBase>();
#endregion
......@@ -174,7 +155,7 @@ namespace FLY.Modbus
//找寄存器
int endAddr = addr + vals.Count() - 1;
RegisterData area_regs = registers;
RegisterData area_regs = (RegisterData)mAreaManager[1];
for (int i = 0; i < area_regs.regs.Count(); i++)
{
......@@ -226,7 +207,7 @@ namespace FLY.Modbus
//找寄存器
int endAddr = addr + vals.Count() - 1;
CoilData area_coils = coils;
CoilData area_coils = mAreaManager[0] as CoilData;
for (int i = 0; i < area_coils.regs.Count(); i++)
{
......@@ -261,14 +242,7 @@ namespace FLY.Modbus
}
}
/// <summary>
/// 获取Modbus的数据值
/// </summary>
/// <param name="dataarea">0,1,3,4数据模型</param>
/// <param name="addr">地址</param>
/// <param name="num">数量</param>
/// <returns></returns>
public abstract object GetModbusData(PLCAddressArea dataarea, int addr, int num);
#endregion
#endregion
......@@ -343,6 +317,20 @@ namespace FLY.Modbus
}
/// <summary>
/// PLC 地址空间, 线圈 or 寄存器
/// </summary>
public enum PLCAddressArea
{
/// <summary>
/// 线圈
/// </summary>
Coil,
/// <summary>
/// 寄存器
/// </summary>
Register
}
/// <summary>
/// 通知命名数据改变是的参数
/// </summary>
......@@ -386,59 +374,11 @@ namespace FLY.Modbus
}
}
/// <summary>
/// 通知Modbus数据改变的参数
/// </summary>
public class ModbusDataChangedEventArgs : EventArgs
{
PLCAddressArea dataarea;
int addr;
int num;
/// <summary>
///
/// </summary>
/// <param name="dataarea">数据类型</param>
/// <param name="addr">地址</param>
/// <param name="num">数量</param>
public ModbusDataChangedEventArgs(PLCAddressArea dataarea, int addr, int num)
{
this.dataarea = dataarea;
this.addr = addr;
this.num = num;
}
/// <summary>
/// 数据类型
/// </summary>
public virtual PLCAddressArea DataArea
{
get { return dataarea; }
}
/// <summary>
/// 地址
/// </summary>
public virtual int Addr
{
get { return addr; }
}
/// <summary>
/// 数量
/// </summary>
public virtual int Num
{
get { return num; }
}
}
/// <summary>
/// NameData 改变事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void NameDataChangedEventHandler(object sender, NameDataChangedEventArgs e);
/// <summary>
/// ModbusData 改变事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ModbusDataChangedEventHandler(object sender, ModbusDataChangedEventArgs e);
}
......@@ -92,8 +92,9 @@ namespace FLY.Modbus
{
if (!mclient.IsConnected)
{
coils.ClearPlanState();
registers.ClearPlanState();
foreach (var areaManager in mAreaManager)
areaManager.ClearPlanState();
//复位全部状态
isInCommunication = false;
p_doing = null;
......@@ -128,6 +129,11 @@ namespace FLY.Modbus
isUpdating = true;
ActUpdateInterval = mStopwatch.Elapsed;
mStopwatch.Restart();
foreach (var areaManager in mAreaManager)
{
areaManager.MakePlanReal();
}
}
}
NextPlan();
......@@ -176,7 +182,7 @@ namespace FLY.Modbus
/// <param name="obj"></param>
void Do_01_callback(bool[] val, object obj)
{
ModbusMapper.Plan p = obj as ModbusMapper.Plan;
Plan p = obj as Plan;
p.isDoing = false;
SetModbusData(PLCAddressArea.Coil, p.addr, val);
......@@ -191,7 +197,7 @@ namespace FLY.Modbus
void Do_03_callback(UInt16[] val, object obj)
{
ModbusMapper.Plan p = obj as ModbusMapper.Plan;
Plan p = obj as Plan;
p.isDoing = false;
SetModbusData(PLCAddressArea.Register, p.addr, val);
isInCommunication = false;
......@@ -219,7 +225,7 @@ namespace FLY.Modbus
/// <summary>
/// 读更新 的计划
/// </summary>
ModbusMapper.Plan p_doing = null;
Plan p_doing = null;
///// <summary>
/////
///// </summary>
......@@ -343,6 +349,18 @@ namespace FLY.Modbus
/// 总寄存器数量
/// </summary>
public int DRCnt { get; private set; }
/// <summary>
/// DRmap分配到 每个寄存器区
/// </summary>
public void Build()
{
DRCnt = DRmap.Count;
//TODO, 应该提前做!!!!
foreach (var areaManager in mAreaManager)
areaManager.BuildArray(DRmap);
}
/// <summary>
/// 创建寄存器更新计划
/// </summary>
......@@ -361,14 +379,9 @@ namespace FLY.Modbus
}
}
DRNeedUpdateCnt = DRmap.Count((dr) => dr.isNeedUpdate);
DRCnt = DRmap.Count;
//TODO, 应该提前做!!!!
registers.BuildArray(DRmap);
coils.BuildArray(DRmap);
registers.MakePlan();
coils.MakePlan();
foreach (var areaManager in mAreaManager)
areaManager.MakePlan();
}
#endregion
}
......
......@@ -53,57 +53,60 @@ namespace FLY.Modbus
{
throw new Exception("还没有执行 BuildArray()");
}
plan.Clear();
int addr = -1;
int num = 0;
for (int i = 0; i < regs.Count(); i++)
lock (plan_buffer)
{
if (!regs[i].dr.isNeedUpdate)
continue;
plan_buffer.Clear();
if (addr == -1)
int addr = -1;
int num = 0;
for (int i = 0; i < regs.Count(); i++)
{
addr = regs[i].dr.addr;
num = regs[i].value.Count();
if (num > maxOfOneRead)
if (!regs[i].dr.isNeedUpdate)
continue;
if (addr == -1)
{
//一片区域已经大于 最大读取寄存器数,分拆
while (num > maxOfOneRead)
addr = regs[i].dr.addr;
num = regs[i].value.Count();
if (num > maxOfOneRead)
{
plan.Add(new Plan(area, addr, maxOfOneRead));
addr += maxOfOneRead;
num -= maxOfOneRead;
//一片区域已经大于 最大读取寄存器数,分拆
while (num > maxOfOneRead)
{
plan.Add(new Plan(area, addr, maxOfOneRead));
addr += maxOfOneRead;
num -= maxOfOneRead;
}
if (num > 0)
plan.Add(new Plan(area, addr, num));
addr = -1;
}
if (num > 0)
plan.Add(new Plan(area, addr, num));
addr = -1;
}
}
else
{
int n = regs[i].dr.addr + regs[i].value.Count() - 1 - addr + 1;
if (n <= maxOfOneRead)
{
num = n;
}
else
{
plan.Add(new Plan(area, addr, num));
addr = -1;
i--;
int n = regs[i].dr.addr + regs[i].value.Count() - 1 - addr + 1;
if (n <= maxOfOneRead)
{
num = n;
}
else
{
plan_buffer.Add(new Plan(area, addr, num));
addr = -1;
i--;
}
}
}
}
}
if (addr != -1)
{
plan.Add(new Plan(area, addr, num));
addr = -1;
if (addr != -1)
{
plan_buffer.Add(new Plan(area, addr, num));
addr = -1;
}
isPlanChanged = true;
}
}
}
}
......@@ -72,8 +72,8 @@ namespace FLY.Modbus.WithThread
{
if (!mclient.IsConnected)
{
coils.ClearPlanState();
registers.ClearPlanState();
foreach (var areaManager in mAreaManager)
areaManager.ClearPlanState();
// DRMap 的数据 与 下端 属性的数据一致
foreach (RegWrite rw in rws)
......@@ -114,6 +114,11 @@ namespace FLY.Modbus.WithThread
/// <returns></returns>
bool UpdateReadData()
{
foreach (var areaManager in mAreaManager)
{
areaManager.MakePlanReal();
}
int curr_area_idx = 0;
while (true)
{
......@@ -254,6 +259,18 @@ namespace FLY.Modbus.WithThread
/// 总寄存器数量
/// </summary>
public int DRCnt { get; private set; }
/// <summary>
/// DRmap分配到 每个寄存器区
/// </summary>
public void Build()
{
DRCnt = DRmap.Count;
//TODO, 应该提前做!!!!
foreach (var areaManager in mAreaManager)
areaManager.BuildArray(DRmap);
}
/// <summary>
/// 创建寄存器更新计划
/// </summary>
......@@ -272,14 +289,9 @@ namespace FLY.Modbus.WithThread
}
}
DRNeedUpdateCnt = DRmap.Count((dr) => dr.isNeedUpdate);
DRCnt = DRmap.Count;
//TODO, 应该提前做!!!!
registers.BuildArray(DRmap);
coils.BuildArray(DRmap);
registers.MakePlan();
coils.MakePlan();
foreach (var areaManager in mAreaManager)
areaManager.MakePlan();
}
#endregion
}
......
......@@ -30,7 +30,7 @@ namespace FLY.OBJComponents.Server
}
List<Plan> planIDs = new List<Plan>();
public List<DataToRegs> DRMap = new List<DataToRegs>();
public List<ModbusMapper_Client> PLCs = new List<ModbusMapper_Client>();
public List<Modbus.WithThread.ModbusMapper_Client> PLCs = new List<Modbus.WithThread.ModbusMapper_Client>();
public Dictionary<string, INotifyPropertyChanged> ObjNames { get; } = new Dictionary<string, INotifyPropertyChanged>();
/// <summary>
......@@ -47,7 +47,7 @@ namespace FLY.OBJComponents.Server
}
public void Init()
{
foreach (ModbusMapper_Client plc in PLCs)
foreach (var plc in PLCs)
{
plc.NameDataChanged += plc_NameDataChanged;
}
......@@ -92,7 +92,7 @@ namespace FLY.OBJComponents.Server
void plc_NameDataChanged(object sender, NameDataChangedEventArgs e)
{
ModbusMapper_Client plc = sender as ModbusMapper_Client;
var plc = sender as Modbus.WithThread.ModbusMapper_Client;
//这是从HMI 更新过来的,不需要向HMI写入
isShield = true;
......@@ -128,13 +128,13 @@ namespace FLY.OBJComponents.Server
DataToRegs dr = drs.Find((_dr) => { return (_dr.propertyName == propertyname && _dr.owner == ObjNames[objname]); });
if (dr == null)
continue;
dr.mapper.PlanAdd(planID, dr);
((Modbus.WithThread.ModbusMapper_Client)dr.mapper).PlanAdd(planID, dr);
if (!plan.mappers.Contains(dr.mapper))
plan.mappers.Add(dr.mapper);
}
foreach (ModbusMapper mapper in plan.mappers)
foreach (var mapper in plan.mappers)
{
mapper.PlanMake();
((Modbus.WithThread.ModbusMapper_Client)mapper).PlanMake();
}
}
......@@ -189,14 +189,14 @@ namespace FLY.OBJComponents.Server
planIDs.Remove(plan);
foreach (var mapper in plan.mappers)
{
mapper.PlanRemove(plan.ID);
((Modbus.WithThread.ModbusMapper_Client)mapper).PlanRemove(plan.ID);
if (!mappers.Contains(mapper))
mappers.Add(mapper);
}
}
foreach (var mapper in mappers)
{
mapper.PlanMake();
((Modbus.WithThread.ModbusMapper_Client)mapper).PlanMake();
}
}
}
......
......@@ -563,7 +563,7 @@ namespace FLY.Weight.Server
foreach (PLCGroup.PLCDevice device in plcgroup.Devices)
{
ModbusMapper_Client plc = new ModbusMapper_Client(new ClientTCP(device.EP));
var plc = new Modbus.WithThread.ModbusMapper_Client(new Modbus.WithThread.ClientTCP(device.EP));
plcos.PLCs.Add(plc);
}
......@@ -614,11 +614,11 @@ namespace FLY.Weight.Server
if (var.DeviceIndex < 0 || var.DeviceIndex >= plcos.PLCs.Count)
continue;
List<ModbusMapper.DataToRegs> drs = plcos.DRMap;
ModbusMapper_Client plc = plcos.PLCs[var.DeviceIndex];
List<Modbus.DataToRegs> drs = plcos.DRMap;
var plc = plcos.PLCs[var.DeviceIndex];
ModbusMapper.DataToRegs dr = plc.MapDataToRegs(
Modbus.DataToRegs dr = plc.MapDataToRegs(
ModbusMapper.TranslateToPLCAddressArea(var.Mode),
var.Addr,
ModbusMapper.TranslateToREG_TYPE(var.Type),
......@@ -628,6 +628,9 @@ namespace FLY.Weight.Server
if (dr != null)
drs.Add(dr);
}
foreach (var plc in plcos.PLCs)
plc.Build();
}
public event PropertyChangedEventHandler PropertyChanged;
......
......@@ -221,7 +221,7 @@ namespace FLY.Winder.Server
foreach (PLCGroup.PLCDevice device in plcgroup.Devices)
{
ModbusMapper_Client plc = new ModbusMapper_Client(new ClientTCP(device.EP));
var plc = new Modbus.WithThread.ModbusMapper_Client(new Modbus.WithThread.ClientTCP(device.EP));
plcos.PLCs.Add(plc);
}
......@@ -236,11 +236,11 @@ namespace FLY.Winder.Server
if (var.DeviceIndex < 0 || var.DeviceIndex >= plcos.PLCs.Count)
continue;
List<ModbusMapper.DataToRegs> drs = plcos.DRMap;
ModbusMapper_Client plc = plcos.PLCs[var.DeviceIndex];
List<Modbus.DataToRegs> drs = plcos.DRMap;
var plc = plcos.PLCs[var.DeviceIndex];
ModbusMapper.DataToRegs dr = plc.MapDataToRegs(
Modbus.DataToRegs dr = plc.MapDataToRegs(
ModbusMapper.TranslateToPLCAddressArea(var.Mode),
var.Addr,
ModbusMapper.TranslateToREG_TYPE(var.Type),
......@@ -250,6 +250,9 @@ namespace FLY.Winder.Server
if (dr != null)
drs.Add(dr);
}
foreach (var plc in plcos.PLCs)
plc.Build();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment