public XJDevice(List <string> filestr, ServerInfo s0) { XJPLCcmd = new XJPLCPackCmdAndDataUnpack(); DataFormLst = new List <DataTable>(); CSVData = new CsvStreamReader(); dgShowLst = new List <DataGridView>(); //获取监控数据 dataformLst 填充 GetPlcDataTableFromFile(filestr); //监控第一个列表数据 考虑下 这个还要不要 因为已经有一个 shift在后面了 if (dataFormLst.Count > 0) { SetPlcReadDMData(dataFormLst[0]); } //设置端口 SetComm(s0); //监控通讯 WatchCommTimer = new System.Timers.Timer(Constant.XJRestartTimeOut); //这里1.5 秒别改 加到常量里 工控机性能不行 WatchCommTimer.Enabled = false; WatchCommTimer.AutoReset = true; WatchCommTimer.Elapsed += new System.Timers.ElapsedEventHandler(WatchTcpTimerEvent); }
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { string valueStr = dgv.SelectedCells[0].Value.ToString(); int rowindex = dgv.SelectedCells[0].RowIndex; string userdata = dgv.Rows[rowindex].Cells["addr"].Value.ToString(); int addr = 0; string area = "D"; string mode = dgv.Rows[rowindex].Cells["mode"].Value.ToString(); ConstantMethod.SplitAreaAndAddr(userdata, ref addr, ref area); int valueInt; if (int.TryParse(valueStr, out valueInt)) { if (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) > -1 && XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) < Constant.M_ID) { device.WriteSingleDData(addr, valueInt, area, mode); } else { if (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) > Constant.HD_ID && XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) < (Constant.Y_ID + 1)) { if (valueInt == 1 || valueInt == 0) { device.WriteSingleMData(addr, valueInt, area, mode); } else { MessageBox.Show(Constant.ErrorMValue); } } } } }
/// <summary> /// 设置通讯类的 命令打包工具 应该是从上层调用的类中指定的 /// </summary> /// <param name="xjplccmd"></param> public void SetXJPLCcmd(XJPLCPackCmdAndDataUnpack xjplccmd) { if (xjplccmd != null) { XJPLCcmd = xjplccmd; } }
public void DgvValueEdit(int rowIndex, int num3) { string userdata = evokDevice.DataForm.Rows[rowIndex]["addr"].ToString(); int addr = 0; string area = "D"; string mode = evokDevice.DataForm.Rows[rowIndex]["mode"].ToString(); ConstantMethod.SplitAreaAndAddr(userdata, ref addr, ref area); if (((XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) > -1) && (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) < 3))) { evokDevice.WriteSingleDData(addr, num3, area, mode); } }
public DTTcpPlcInfo(int addr, string areaIn, string Mode, int plcId) { this.relativeaddr = addr; this.StrArea = areaIn; //区分 dvp15mc 和 As PLC if (plcId == Constant.xzjDeivceId) { intArea = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(areaIn); absAddr = XJPLCPackCmdAndDataUnpack.RelAbsGet(addr, intArea, 0); } else { absAddr = DTTcpCmdPackAndDataUnpack.GetAbsAddrFromStr(relativeaddr, StrArea); intArea = DTTcpCmdPackAndDataUnpack.GetIntAreaFromStr(StrArea); } ValueMode = Mode; }
//传入相对地址 和区域 单双字 public XJPlcInfo(int addr, string areaIn, string valuemode) { this.relativeaddr = addr; this.StrArea = areaIn; absAddr = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(relativeaddr, StrArea); intArea = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(StrArea); valueMode = valuemode; //D区两个字节 if (intArea < Constant.M_ID) { ByteValue = new byte[2]; } else { ByteValue = new byte[1]; } }
/// <summary> /// XY 地址 8进制转换成十进制 进行类建立 /// </summary> /// <param name="addr"></param> /// <returns></returns> public XJPlcInfo[] GetPlcInfo(int addr, int count, string XYM, string mode) { List <XJPlcInfo> plcinforlst = new List <XJPlcInfo>(); int addrreal = addr; if (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(XYM.Trim()) > Constant.HM_ID) { addrreal = ConstantMethod.GetXYAddr8To10(addr); } for (int i = 0; i < count; i++) { XJPlcInfo tmpInfo = new XJPlcInfo(addrreal, XYM.Trim(), mode); tmpInfo.Xuhao = -1; plcinforlst.Add(tmpInfo); addrreal++; } return(plcinforlst.ToArray()); }
public XJDevice(List <string> filestr, PortParam p0) { IsCommSet = true; XJPLCcmd = new XJPLCPackCmdAndDataUnpack(); DataFormLst = new List <DataTable>(); CSVData = new CsvStreamReader(); dgShowLst = new List <DataGridView>(); //获取监控数据 dataformLst 填充 GetPlcDataTableFromFile(filestr); //找一下串口 不存在就报错 退出 portParam = p0;// ConstantMethod.LoadPortParam(Constant.ConfigSerialportFilePath); if (!SerialPort.GetPortNames().Contains(portParam.m_portName)) { MessageBox.Show(Constant.NoSerialPort + portParam.m_portName); ConstantMethod.AppExit(); } //监控第一个列表数据 考虑下 这个还要不要 因为已经有一个 shift在后面了 if (dataFormLst.Count > 0) { SetPlcReadDMData(dataFormLst[0]); } //设置端口 SetComm(p0); //监控通讯 WatchCommTimer = new System.Timers.Timer(Constant.XJRestartTimeOut); //这里1.5 秒别改 加到常量里 工控机性能不行 WatchCommTimer.Enabled = false; WatchCommTimer.AutoReset = true; WatchCommTimer.Elapsed += new System.Timers.ElapsedEventHandler(WatchTimerEvent); }
/// <summary> /// 针对信捷PLC 进行设备的存在获取 /// </summary> /// <returns></returns> public XJDevice(List <string> filestr) { XJPLCcmd = new XJPLCPackCmdAndDataUnpack(); DataFormLst = new List <DataTable>(); CSVData = new CsvStreamReader(); dgShowLst = new List <DataGridView>(); //获取监控数据 dataformLst 填充 GetPlcDataTableFromFile(filestr); //找一下串口 不存在就报错 退出 if (!ConstantMethod.XJFindPort(1)) { MessageBox.Show(DeviceId + Constant.ConnectMachineFail); //报错 在外面调试 需要隐藏 //ConstantMethod.AppExit(); } portParam = ConstantMethod.LoadPortParam(Constant.ConfigSerialportFilePath); //监控第一个列表数据 考虑下 这个还要不要 因为已经有一个 shift在后面了 if (dataFormLst.Count > 0) { SetPlcReadDMData(dataFormLst[0]); } //设置端口 SetComm(portParam); //监控通讯 WatchCommTimer = new System.Timers.Timer(Constant.XJRestartTimeOut); //这里1.5 秒别改 加到常量里 工控机性能不行 WatchCommTimer.AutoReset = true; WatchCommTimer.Elapsed += new System.Timers.ElapsedEventHandler(WatchTimerEvent); }
public void DgvInOutEdit(int rowIndex, bool editEnable) { string s = evokDevice.DataForm.Rows[rowIndex]["param1"].ToString(); string str2 = evokDevice.DataForm.Rows[rowIndex]["param2"].ToString(); string userdata = evokDevice.DataForm.Rows[rowIndex]["addr"].ToString(); string area = "D"; int addr = 0; ConstantMethod.SplitAreaAndAddr(userdata, ref addr, ref area); int result = 0; int num4 = 0; if (int.TryParse(s, out result) && int.TryParse(str2, out num4)) { if (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area) < 3) { evokDevice.DPlcInfo[result].IsInEdit = editEnable; } else { evokDevice.MPlcInfoAll[result][num4].IsInEdit = editEnable; } } }
/// <summary> /// 串口数据接收 针对信捷PLC /// 数据没有结束符 只能通过校验来确认 /// 信捷PLC 通讯模式 发送一条带DM 区域的指令 返回所有数据 /// 数据错误需要超时机制来进行恢复 如果超时一定次数 则判断中断 机器不存在 // 数据长度达到 就进行数据处理判断 同时发送下一组读取命令 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void XJPLC_SerialPort_Received(object sender, SerialPortEvents e) { if (e.BufferData != null) { m_buffer.AddRange(e.BufferData); //返回命令统一都是0X01开头 如果不是则移除 if (m_buffer[0] != Constant.XJHeader) { m_buffer.RemoveAt(0); } if ((m_buffer.Count > receivedByteCount)) { m_buffer.Clear(); } //收到数据就清空错误指示器,如果长时间通讯错误 肯定会一直往上加 ErrorConnCount = 0; #region 数据长度合格了 //数据接收超长了 也清空 数据刚好相等 头几个数据相同 if (m_buffer.Count == receivedByteCount) { //符合校验规则 if (XJPLCPackCmdAndDataUnpack.IsEnd(m_buffer.ToArray())) { if ((!isDeviceReady) && (ConstantMethod.compareByteStrictly(m_buffer.ToArray(), XJPLCcmd.CmdIn))) { #region 设备未连接 //设备通了 要开始 连接了哦 准备好了 //设置标志位 打开监控定时器 设置发送和 接收命令 isDeviceReady = true; isGoToGetData = true; ErrorConnCount = 0; SetCmdOutToCmdReadDMDataOut(); m_buffer.Clear(); #endregion } else { //设备连接情况下 是写数据区域命令的反馈 还是读数据区域命令的反馈 if (isWriteCmd) { ErrorConnCount = 0; #region 设备连接了 发送设置DM区域数据 //操做XJPLCcmd.CmdOut 只能在一条主线上做 不能再好多地方不然会出错 //这样 写寄存器的数据就要先放在一个缓存寄存命令里 SetCmdOut(XJPLCcmd.CmdSetBDREGOut, XJPLCcmd.CmdSetBDREGIn.Count()); SetCmdIn(XJPLCcmd.CmdSetBDREGIn); if (ConstantMethod.compareByte(m_buffer.ToArray(), XJPLCcmd.CmdIn)) { isWriteCmd = false; SetCmdOutToCmdReadDMDataOut(); } #endregion } else { #region 数据处理 ErrorConnCount = 0; //device重新打包监控数据命令 if (IsRePackCmdReadDMDataOut) { if (IsRepackDone) { SetCmdOutToCmdReadDMDataOut(); IsRePackCmdReadDMDataOut = false; IsRePackymp = true; m_buffer.Clear(); } } else //处理函数不为空 然后 数据开头也对 那就处理数据呗 if ((EventDataProcess != null)) { if (ConstantMethod.compareByte(m_buffer.ToArray(), Constant.XJReadDataCmdCheck)) { if (IsRePackymp) { IsRePackCmdReadDMDataOut = false; } DataProcessEventArgs.Byte_buffer = m_buffer.ToArray(); EventDataProcess(this, DataProcessEventArgs); } } #endregion } } } //在读的过程当中 如果遇到要写 那就先写 有没有在优化 if (IsGoToGetData && isNoConnection == false) { m_SerialPort.Send(XJPLCcmd.CmdOut.ToArray()); } ErrorConnCount = 0; m_buffer.Clear(); #endregion 数据长度合格了 } else { //收到字节数超出预计长度了 ErrorConnCount = 0; if (m_buffer.Count > receivedByteCount) { m_buffer.Clear(); } } } ////GC.Collect(); ////GC.WaitForPendingFinalizers(); }
/// <summary> /// dataform中的数据 与 dplcinfo 和 mplcinfoall 集合对应起来 这样 更新速度会很快 /// </summary> /// <param name="datafm"></param> /// <param name="dAll"></param> /// <param name="mAll"></param> /// <returns></returns> private bool FindIndexInPlcInfo(DataTable datafm, List <XJPlcInfo> dAll, List <List <XJPlcInfo> > mAll) { foreach (DataRow row in datafm.Rows) { if (row == null) { continue; } int mAddr = 0; //地址 int mArea; string strSplit1; string strSplit2; //地址区域 string DSmode; //单字还是双字 strSplit1 = Regex.Replace(row["addr"].ToString().Trim(), "[A-Z]", "", RegexOptions.IgnoreCase); //取字母 strSplit2 = Regex.Replace(row["addr"].ToString().Trim(), "[0-9]", "", RegexOptions.IgnoreCase); strSplit1 = strSplit1.Trim(); strSplit2 = strSplit2.Trim(); DSmode = row["mode"].ToString().Trim(); //地址超了 无效 暂且定XDM 最大69999 if (!int.TryParse(strSplit1, out mAddr) || (mAddr < 0) || (mAddr > Constant.XJMaxAddr)) { continue; } int count; if (!int.TryParse(row["count"].ToString().Trim(), out count)) { continue; } mArea = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(strSplit2); if (mArea > Constant.HM_ID) { mAddr = ConstantMethod.GetXYAddr8To10(mAddr); } mAddr = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(mAddr, strSplit2); if (mArea < 0) { continue; } if (row["param1"] != null && row["param2"] != null) { int[] s = FindValueIndexFromDPlcInfo(mAddr, mArea, DSmode); row["param1"] = s[0]; row["param2"] = s[1]; //让集合 把dataform 也保存下 方便更新数据 if (mArea < Constant.M_ID) { if (!(s[0] > -1)) { continue; } DPlcInfo[s[0]].BelongToDT = datafm; DPlcInfo[s[0]].Row = datafm.Rows.IndexOf(row); } else { if (!(s[0] > -1 && s[1] > -1)) { continue; } MPlcInfoAll[s[0]][s[1]].BelongToDT = datafm; MPlcInfoAll[s[0]][s[1]].Row = datafm.Rows.IndexOf(row); } } } return(true); }
/// <summary> /// 这里增加一个 就是 主form太大了 分割一个form出来 但是 绑定 还是在原来那个主form上 /// </summary> /// <param name="dataForm0"></param> void SplitPackCmdReadDMDataOut(DataTable dataForm0, DataTable dataForm1) { List <XJPlcInfo> plcInfoLst = new List <XJPlcInfo>(); List <XJPlcInfo> MPlcInfo = new List <XJPlcInfo>(); foreach (DataRow row in dataForm0.Rows) { int mAddr = 0; int count = 0; string strSplit1; string strSplit2; string DSmode; //单字还是双字 #region 获取地址 个数 区域 创建plcinfo类 并添加到集合 if (row == null) { return; } if (row["addr"].ToString() == null || row["mode"].ToString() == null || row["count"].ToString() == null) { return; } ; //添加各个单元 //取数字 用替代的字符的方法 取数组就替换字母为空 取字母就替换数字 strSplit1 = Regex.Replace(row["addr"].ToString(), "[A-Z]", "", RegexOptions.IgnoreCase); //取字母 strSplit2 = Regex.Replace(row["addr"].ToString(), "[0-9]", "", RegexOptions.IgnoreCase); DSmode = row["mode"].ToString(); if (!int.TryParse(row["count"].ToString(), out count)) { continue; } //地址超了 无效 暂且定XDM 最大69999 if (!int.TryParse(strSplit1, out mAddr) || (mAddr < 0) || (mAddr > Constant.XJMaxAddr)) { continue; } //字母大于4 无效地址 if (strSplit2.Count() > 3) { continue; } //这里数组进行统计 if (DSmode.Equals(Constant.DoubleMode) && (XJPLCPackCmdAndDataUnpack.AreaGetFromStr(strSplit2) < Constant.M_ID)) { count = count * 2; } //传入数据起始地址 个数 区域 模式 XJPlcInfo[] tmpInfoLst = XJPLCcmd.GetPlcInfo(mAddr, count, strSplit2, DSmode); if (tmpInfoLst.Count() > 0) { plcInfoLst.AddRange(tmpInfoLst); } #endregion } #region 排序 去重复 统计DM 起始点 //排序 按照绝对地址 plcInfoLst = plcInfoLst.OrderBy(x => x.AbsAddr).ToList(); //去重复 plcInfoLst = plcInfoLst.Distinct(new ModelComparer()).ToList(); //分离D 区 M区 DPlcInfo = plcInfoLst.FindAll(t => t.IntArea < (Constant.HSD_ID + 1)); MPlcInfo = plcInfoLst.FindAll(t => t.IntArea > (Constant.HSD_ID)); DPlcInfo = InsertPlcInfo(DPlcInfo); //将D区分解出来 出来 变成一个一个单个的地址 尽量保持连续 MPlcInfo = InsertPlcInfo(MPlcInfo); plcInfoLst = DPlcInfo.Union(MPlcInfo).ToList <XJPlcInfo>(); #endregion #region 根据断点 建立命令的表格缓冲lst 然后创建读取DM区域的命令 //开始打包 List <int> addrLst = new List <int>(); //连续地址的起始地址 List <int> idLst = new List <int>(); //地址是D xy HSD List <int> addrcount = new List <int>(); //起始地址开始 读取几个寄存器 List <int> breakPoint = new List <int>(); //在 //首先要确定断点 breakPoint.Add(0); //获取不连续点的位置 D区域 for (int i = 0; i < plcInfoLst.Count - 1; i++) { if (((plcInfoLst[i + 1].RelAddr - plcInfoLst[i].RelAddr) > 1) || (plcInfoLst[i + 1].IntArea != plcInfoLst[i].IntArea)) { int bp = i + 1; breakPoint.Add(bp); } } breakPoint.Add(plcInfoLst.Count); //d区在前面,M区在后面 根据断点来区分 //统计D区起始地址个数 统计M区起始地址个数 //D区返回数据可以根据Dplcinfo集合来预算 //但M区需要知道M起始地址个数 for (int j = 0; j < breakPoint.Count; j++) { if (breakPoint[j] < plcInfoLst.Count) { addrLst.Add(plcInfoLst[breakPoint[j]].AbsAddr); idLst.Add(plcInfoLst[breakPoint[j]].IntArea); addrcount.Add(plcInfoLst[breakPoint[j + 1] - 1].RelAddr - plcInfoLst[breakPoint[j]].RelAddr + 1); } } //这里d区的话 需要指定一下双字情况下的 另外一个字节 FindHighPlcInfo(DPlcInfo); //这里M区麻烦一点 分成n个M单元组 每个单元组 有个起始地址 MPlcInfoAll = new List <List <XJPlcInfo> >(); for (int i = 0; i < addrLst.Count; i++) { List <XJPlcInfo> mplst = new List <XJPlcInfo>(); if (idLst[i] > Constant.HSD_ID) { for (int k = 0; k < addrcount[i]; k++) { XJPlcInfo p = new XJPlcInfo(); p.ValueMode = Constant.BitMode; p.ByteValue = new byte[1]; p.IntArea = idLst[i]; p.AbsAddr = addrLst[i] + k; p.Xuhao = k; mplst.Add(p); } } if (mplst.Count > 0) { MPlcInfoAll.Add(mplst); } } int mCount = 0; for (int i = 0; i < MPlcInfoAll.Count; i++) { double cntdb = (double)MPlcInfoAll[i].Count / 8; mCount = mCount + (int)Math.Ceiling(cntdb); } //绑定主form FindIndexInPlcInfo(dataForm1, DPlcInfo, MPlcInfoAll); XJPLCcmd.PackCmdReadDMDataOut(addrLst, idLst, addrcount, 5 + DPlcInfo.Count * 2 + mCount); #endregion addrLst = null; idLst = null; addrcount = null; breakPoint = null; //GC.Collect(); //GC.WaitForPendingFinalizers(); }
public bool WriteMultiPleDMData(int relAddr, int[] value, string area, string mode) { int intArea = XJPLCPackCmdAndDataUnpack.AreaGetFromStr(area); List <int> mvalueLst = new List <int>(); if (intArea < Constant.M_ID) { if (mode.Equals(Constant.DoubleMode)) { int dcount = value.Count() * 2; List <int> valueLst = new List <int>(); foreach (int valuevaluesingle in value) { int addr_high = (int)((valuevaluesingle & 0xFFFF0000) >> 16); int addr_low = valuevaluesingle & 0xFFFF; //判断下西门子的 if (area.Contains(Constant.SimensDB)) { valueLst.Add(addr_high); valueLst.Add(addr_low); } else { valueLst.Add(addr_low); valueLst.Add(addr_high); } } return(SetMultipleDArea(relAddr, dcount, valueLst.ToArray(), area)); } else { if (mode.Equals(Constant.SingleMode)) { return(SetMultipleDArea(relAddr, value.Count(), value, area)); } else { return(false); } } } else { string strvalue = ""; //8个数据一组 for (int i = 0; i < value.Count(); i++) { string s = value[i].ToString(); strvalue = strvalue.Insert(0, s); if ((((i + 1) % 8) == 0) || (i == value.Count() - 1)) { mvalueLst.Add(Convert.ToInt32(strvalue, 2)); strvalue = ""; } } } //这里传入的数据 应该是 return(SetMultipleMArea(relAddr, value.Count(), mvalueLst.ToArray(), area)); }