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; } } }