public override bool Read <T>(out List <T> value, Dictionary <string, string> parm) { lock (lockObject) { value = new List <T>(); bool result = true; //读取开始点 if (!parm.ContainsKey("Start") && !parm.ContainsKey("Address")) { All.Class.Error.Add("数据读取参数中不包含寄存器地址", Environment.StackTrace); return(false); } ushort tmpAddress = 0; if (parm.ContainsKey("Start")) { tmpAddress = parm["Start"].ToUshort(); } if (parm.ContainsKey("Address")) { tmpAddress = parm["Address"].ToUshort(); } Class.TypeUse.TypeList t = All.Class.TypeUse.GetType <T>(); //读取区域 if (!parm.ContainsKey("Code")) { switch (t) { case Class.TypeUse.TypeList.Boolean: parm.Add("Code", "M"); break; case Class.TypeUse.TypeList.String: case Class.TypeUse.TypeList.UShort: case Class.TypeUse.TypeList.Int: case Class.TypeUse.TypeList.Long: case Class.TypeUse.TypeList.Byte: case Class.TypeUse.TypeList.Float: case Class.TypeUse.TypeList.Double: parm.Add("Code", "D"); break; } } else { switch (t) { case Class.TypeUse.TypeList.Boolean: if (parm["Code"].ToUpper() != "X" && parm["Code"].ToUpper() != "M" && parm["Code"].ToUpper() != "Y") { All.Class.Error.Add("读取参数中区域类型和返回数据类型不一致", Environment.StackTrace); return(false); } break; case Class.TypeUse.TypeList.String: case Class.TypeUse.TypeList.UShort: case Class.TypeUse.TypeList.Int: case Class.TypeUse.TypeList.Long: case Class.TypeUse.TypeList.Byte: case Class.TypeUse.TypeList.Float: case Class.TypeUse.TypeList.Double: if (parm["Code"].ToUpper() != "D") { All.Class.Error.Add("读取参数中区域类型和返回数据类型不一致", Environment.StackTrace); } break; } } //读取结束点 ushort tmpLen = 1; int tmpBoolLen = 0; int tmpStart = 0; if (!parm.ContainsKey("End")) { parm.Add("End", tmpAddress.ToString()); } ushort end = parm["End"].ToUshort(); if (end < tmpAddress) { All.Class.Error.Add("读取参数中结束点大于起始点", Environment.StackTrace); return(false); } switch (parm["Code"].ToUpper()) { case "M": tmpLen = (ushort)(((int)Math.Floor(end / 8f) - (int)Math.Floor(tmpAddress / 8f) + 1) & 0xFFFF); tmpStart = tmpAddress % 8; tmpBoolLen = (tmpLen - 1) * 8 - tmpStart + (end % 8) + 1; tmpAddress = (ushort)((int)Math.Floor(tmpAddress / 8f) + 0x100); break; case "X": tmpLen = (ushort)(((int)Math.Floor(end / 10f) - (int)Math.Floor(tmpAddress / 10f) + 1) & 0xFFFF); tmpStart = tmpAddress % 10; tmpBoolLen = (tmpLen - 1) * 8 - tmpStart + (end % 10) + 1; tmpAddress = (ushort)((int)Math.Floor(tmpAddress / 10f) + 0x80); break; case "Y": tmpLen = (ushort)(((int)Math.Floor(end / 10f) - (int)Math.Floor(tmpAddress / 10f) + 1) & 0xFFFF); tmpStart = tmpAddress % 10; tmpBoolLen = (tmpLen - 1) * 8 - tmpStart + (end % 10) + 1; tmpAddress = (ushort)((int)Math.Floor(tmpAddress / 10f) + 0xA0); break; case "D": tmpLen = (ushort)(2 * (end - tmpAddress + 1) & 0xFFFF); tmpAddress = (ushort)((tmpAddress * 2 + 0x1000) & 0xFFFF); break; case "T": case "C": case "S": All.Class.Error.Add("读取参数中的区域暂时没有驱动,须要添加", Environment.StackTrace); break; default: All.Class.Error.Add("读取参数中的区域错误,PLC没有此区域", Environment.StackTrace); break; } int len = 4 + 2 * tmpLen; byte[] sendBuff = new byte[11]; byte[] readBuff; sendBuff[0] = 0x02; sendBuff[1] = 0x30; Array.Copy(Encoding.ASCII.GetBytes(string.Format("{0:X4}", tmpAddress)), 0, sendBuff, 2, 4); Array.Copy(Encoding.ASCII.GetBytes(string.Format("{0:X2}", tmpLen)), 0, sendBuff, 6, 2); sendBuff[8] = 0x03; byte sumLow, sumHigh; All.Class.Check.SumCheck(sendBuff.ToArray(), 1, sendBuff.Length - 3, out sumLow, out sumHigh); Array.Copy(Encoding.ASCII.GetBytes(string.Format("{0:X2}", sumLow)), 0, sendBuff, 9, 2); if (WriteAndRead <byte[], byte[]>(sendBuff, len, out readBuff)) { if (readBuff[0] != 0x02 && readBuff[readBuff.Length - 3] != 0x03) { All.Class.Error.Add("读取参数帧头或帧尾校验失败", Environment.StackTrace); return(false); } All.Class.Check.SumCheck(readBuff.ToArray(), 1, readBuff.Length - 3, out sumLow, out sumHigh); if (Encoding.ASCII.GetString(readBuff, readBuff.Length - 2, 2) != string.Format("{0:X2}", sumLow)) { All.Class.Error.Add("读取参数和校验失败", Environment.StackTrace); return(false); } byte[] tmp; bool[] tmpBool; switch (parm["Code"].ToUpper()) { case "X": case "Y": case "M": tmp = Encoding.ASCII.GetString(readBuff, 1, readBuff.Length - 4).ToHexBytes(); tmpBool = All.Class.Num.Byte2Bool(tmp); for (int i = tmpStart, j = 0; i < tmpBool.Length && j < tmpBoolLen; i++, j++) { value.Add((T)(object)tmpBool[i]); } break; case "D": tmp = All.Class.Num.SwitchHighAndLow(Encoding.ASCII.GetString(readBuff, 1, readBuff.Length - 4).ToHexBytes()); switch (t) { case Class.TypeUse.TypeList.Byte: for (int i = 0; i < tmp.Length; i++) { value.Add((T)(object)tmp[i]); } break; case Class.TypeUse.TypeList.UShort: for (int i = 0; i < tmp.Length - 1; i = i + 2) { value.Add((T)(object)(ushort)((((tmp[i] << 8) + tmp[i + 1])) & 0xFFFF)); } break; case Class.TypeUse.TypeList.Long: for (int i = 0; i < tmp.Length - 1; i = i + 2) { value.Add((T)(object)(long)(((tmp[i] << 8) + tmp[i + 1]))); } break; case Class.TypeUse.TypeList.Float: if ((tmp.Length % 4) != 0) { All.Class.Error.Add("Fxplc读取单精度浮点数时,必须一次读4个字节"); return(false); } for (int i = 0; i < tmp.Length - 1; i = i + 4) { value.Add((T)(object)BitConverter.ToSingle(tmp, i)); } break; case Class.TypeUse.TypeList.Double: if ((tmp.Length % 8) != 0) { All.Class.Error.Add("Fxplc读取双精度浮点数时,必须一次读8个字节"); return(false); } for (int i = 0; i < tmp.Length - 1; i = i + 8) { value.Add((T)(object)BitConverter.ToDouble(tmp, i)); } break; case Class.TypeUse.TypeList.String: value.Add((T)(object)Encoding.ASCII.GetString(tmp)); break; case Class.TypeUse.TypeList.Int: int tmpInt = 0; for (int i = 0; i < tmp.Length - 1; i = i + 2) { tmpInt = (tmp[i] << 8) + tmp[i + 1]; if ((tmpInt & 0x8000) == 0x8000) { tmpInt = -(tmpInt ^ 0xFFFF) - 1; } value.Add((T)(object)tmpInt); } break; } break; default: throw new Exception("Error"); } } else { result = false; } return(result); } }
public override bool Read <T>(out List <T> value, Dictionary <string, string> parm) { lock (lockObject) { bool result = true; value = new List <T>(); if (!parm.ContainsKey("Start") && !parm.ContainsKey("Address")) { All.Class.Error.Add("数据读取参数中不包含寄存器地址", Environment.StackTrace); return(false); } ushort tmpAddress = 0; if (parm.ContainsKey("Start")) { tmpAddress = parm["Start"].ToUshort(); } if (parm.ContainsKey("Address")) { tmpAddress = parm["Address"].ToUshort(); } if (!parm.ContainsKey("End")) { parm.Add("End", tmpAddress.ToString()); } ushort end = parm["End"].ToUshort(); if (end < tmpAddress) { All.Class.Error.Add("读取参数中结束点大于起始点", Environment.StackTrace); return(false); } Class.TypeUse.TypeList t = All.Class.TypeUse.GetType <T>(); string code = "BR"; //读取区域 if (!parm.ContainsKey("Code")) { switch (t) { case Class.TypeUse.TypeList.Boolean: parm.Add("Code", "M"); code = "BR"; break; case Class.TypeUse.TypeList.String: case Class.TypeUse.TypeList.UShort: case Class.TypeUse.TypeList.Int: case Class.TypeUse.TypeList.Long: case Class.TypeUse.TypeList.Byte: case Class.TypeUse.TypeList.Float: case Class.TypeUse.TypeList.Double: parm.Add("Code", "D"); code = "WR"; break; } } else { switch (t) { case Class.TypeUse.TypeList.Boolean: if (parm["Code"].ToUpper() != "X" && parm["Code"].ToUpper() != "M" && parm["Code"].ToUpper() != "Y") { All.Class.Error.Add("读取参数中区域类型和返回数据类型不一致", Environment.StackTrace); return(false); } code = "BR"; break; case Class.TypeUse.TypeList.String: case Class.TypeUse.TypeList.UShort: case Class.TypeUse.TypeList.Int: case Class.TypeUse.TypeList.Long: case Class.TypeUse.TypeList.Byte: case Class.TypeUse.TypeList.Float: case Class.TypeUse.TypeList.Double: if (parm["Code"].ToUpper() != "D") { All.Class.Error.Add("读取参数中区域类型和返回数据类型不一致", Environment.StackTrace); } code = "WR"; break; } } //读取长度 int readCount = end - tmpAddress + 1; if (parm["Code"].ToUpper() == "X" || parm["Code"].ToUpper() == "Y") { try { readCount = Convert.ToInt16(string.Format("{0}", tmpAddress), 8) - Convert.ToInt16(string.Format("{0}", end), 8) + 1; } catch { All.Class.Error.Add(string.Format("读取参数中,读取地址错误,读取的地址{0}或结束的地址{1}不是8进制数", tmpAddress, end), Environment.StackTrace); return(false); } } //返回长度 int len = 6 + readCount + (check ? 2 : 0) + (crlf ? 2 : 0); if (parm["Code"].ToUpper() == "D") { len = 6 + readCount * 4 + (check ? 2 : 0) + (crlf ? 2 : 0); } List <byte> sendBuff = new List <byte>(); sendBuff.Add(0x05); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X2}", address))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X2}", 0xFF))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0}", code))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X1}", delay))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0}", parm["Code"].ToUpper()))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X4}", tmpAddress))); sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X2}", readCount))); if (check) { sendBuff.AddRange(Encoding.ASCII.GetBytes(string.Format("{0:X2}", All.Class.Check.SumCheck(sendBuff.ToArray(), 1, sendBuff.Count - 1)))); } if (crlf) { sendBuff.Add(0x0D); sendBuff.Add(0x0A); } byte[] readBuff; if (WriteAndRead <byte[], byte[]>(sendBuff.ToArray(), len, out readBuff)) { if (readBuff[0] != sendBuff[0] || readBuff[1] != sendBuff[1] || readBuff[2] != sendBuff[2] || readBuff[3] != sendBuff[3] || readBuff[4] != sendBuff[4]) { All.Class.Error.Add("读取参数帧头或帧尾校验失败", Environment.StackTrace); All.Class.Error.Add(string.Format("读取帧为:{0}", All.Class.Num.Hex2Str(readBuff))); return(false); } switch (parm["Code"].ToUpper()) { case "X": case "Y": case "M": for (int i = 0; i < readCount; i++) { value.Add((T)(object)(readBuff[5 + i] == 0x31)); } break; case "D": switch (t) { case Class.TypeUse.TypeList.String: value.Add((T)(object)Encoding.ASCII.GetString(readBuff, 5, readCount * 4)); break; case Class.TypeUse.TypeList.Byte: for (int i = 0; i < readCount * 4; i++) { value.Add((T)(object)readBuff[5 + i]); } break; case Class.TypeUse.TypeList.Double: if ((readCount % 4) != 0) { All.Class.Error.Add("Fxplc读取双精度浮点数时,必须一次读4个D点"); return(false); } for (int i = 0; i < readCount; i++) { value.Add((T)(object)BitConverter.ToDouble(All.Class.Num.Str2Hex(Encoding.ASCII.GetString(readBuff, 5 + i * 16, 16)), 0)); } break; case Class.TypeUse.TypeList.Float: if ((readCount % 2) != 0) { All.Class.Error.Add("Fxplc读取单精度浮点数时,必须一次读2个D点"); return(false); } for (int i = 0; i < readCount; i++) { value.Add((T)(object)BitConverter.ToDouble(All.Class.Num.Str2Hex(Encoding.ASCII.GetString(readBuff, 5 + i * 8, 8)), 0)); } break; case Class.TypeUse.TypeList.Int: int tmpInt = 0; for (int i = 0; i < readCount; i++) { tmpInt = (Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 5 + i * 4, 2), 16) << 8) + (Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 7 + i * 4, 2), 16)); if ((tmpInt & 0x8000) == 0x8000) { tmpInt = -((tmpInt ^ 0xFFFF) + 1); } value.Add((T)(object)tmpInt); } break; case Class.TypeUse.TypeList.Long: for (int i = 0; i < readCount; i++) { value.Add((T)(object)(long)((Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 5 + i * 4, 2), 16) << 8) + (Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 7 + i * 4, 2), 16)))); } break; case Class.TypeUse.TypeList.UShort: for (int i = 0; i < readCount; i++) { value.Add((T)(object)(ushort)((Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 5 + i * 4, 2), 16) << 8) + (Convert.ToInt32(Encoding.ASCII.GetString(readBuff, 7 + i * 4, 2), 16)))); } break; } break; default: throw new Exception("Error"); } } else { result = false; } return(result); } }