using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace UPPLibs { /* *结构名称:struReadData *创建人:韩荣伟 *创建时间:2010-10-30 *功能描述:结构,用于存放读对象解析数据 */ struct struReadData { //终端类型 public byte flagDTN; //逻辑编号 public byte[] addrDNL; //主站地址 public byte flagMSTA; //帧序号 public byte flagFSEQ; //功能标志 public byte flagCtrlF; //测量点标志 public byte flagPoint; //数据项编号 public byte[] numPairs; } /* *结构名称:struWriteData *创建人:韩荣伟 *创建时间:2010-10-30 *功能描述:结构,用于存放写对象待封装数据 */ struct struWriteData { //终端类型 public byte flagDTN; //逻辑编号 public byte[] addrDNL; //主站地址 public byte flagMSTA; //帧序号 public byte flagFSEQ; //功能标志 public byte flagCtrlF; //测量点标志 public byte flagPoint; //权限标志 public byte flagAUT; //密码 public byte[] passwd; //数据项编号 public byte[] numPairs; //对时处理标志 public bool isTimeCorrecting; } /* *结构名称:struFrame *创建人:韩荣伟 *创建时间:2010-10-30 *功能描述:结构,用于存放帧解析数据 */ struct struFrame { //终端类型 public byte flagDTN; //逻辑编号 public byte[] addrDNL; //主站地址 public byte flagMSTA; //帧内序号 public byte flagISEQ; //帧序号 public byte flagFSEQ; //控制码 public byte flagCtrl; //传送方向 public byte flagCtrlD; //异常标志 public byte flagCtrlE; //功能标志 public byte flagCtrlF; //数据长度 public int lenData; //数据字符串 public byte[] strData; public object userData; public string tName; public object userData2; //public bool isCtrl; //public bool isData; public bool isTimeCorrectting; }; /* *结构名称:struRequestInQueue *创建人:韩荣伟 *创建时间:2010-10-30 *功能描述:结构,用于存放请求信息,放入队列 */ struct struRequestInQueue { //帧信息 public struFrame frameInfo; //帧字节串 public byte[] frameBytes; //是否匹配 public bool bMatchOK; }; /* *类名称:UPPHandler *创建人:韩荣伟 *创建时间:2010-10-30 *功能描述:上行协议处理类 */ class UPPHandler { /* *方法名称:countCS *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:byte[] bytes 待计算的字节数组, *int start 字节数组开始位置, *int len 字节数组指定长度 *返回描述:int CS校验数 *功能描述:对字节数组计算CS校验数 */ public static int countCS(byte[] bytes, int start, int len) { if (len > bytes.Length || len <= 0) { return -1; } int sum = 0; for (int i = start; i < (len + start); i++) { sum += bytes[i]; } return sum % 0x100; } /* *方法名称:PreframePacking *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:byte flagCtrlF 功能码, *object obj 参数对象, *ref struFrame sFrame 预封装得到的帧结构 *返回描述:bool true 成功,false 失败 *功能描述:由参数对象,预封装成帧结构 */ public static bool PreframePacking(byte flagCtrlF, object obj, ref struFrame sFrame) { bool res = true; sFrame.addrDNL = new byte[2]; sFrame.flagCtrlE = 0; sFrame.flagCtrlD = 0; sFrame.flagCtrlF = flagCtrlF; switch (flagCtrlF) { case 0x00: //strComment += "中继"; break; //"读当前数据" case 0x01: struReadData rdData = (struReadData)obj; sFrame.flagDTN = rdData.flagDTN; sFrame.addrDNL[0] = rdData.addrDNL[0]; sFrame.addrDNL[1] = rdData.addrDNL[1]; sFrame.flagMSTA = rdData.flagMSTA; sFrame.flagISEQ = (byte)0; sFrame.flagFSEQ = rdData.flagFSEQ; sFrame.lenData = 1 + rdData.numPairs.Length; sFrame.strData = new byte[sFrame.lenData]; sFrame.strData[0] = rdData.flagPoint; for (int i = 0; i < rdData.numPairs.Length; i++) { sFrame.strData[i + 1] = rdData.numPairs[i]; } break; case 0x02: //strComment += "读任务数据"; break; case 0x04: //strComment += "读编程日志"; break; case 0x07: //strComment += "实时写对象参数"; break; case 0x08: //strComment += "写对象参数"; struWriteData wrData = (struWriteData)obj; sFrame.flagDTN = wrData.flagDTN; sFrame.addrDNL[0] = wrData.addrDNL[0]; sFrame.addrDNL[1] = wrData.addrDNL[1]; sFrame.flagMSTA = wrData.flagMSTA; sFrame.flagISEQ = (byte)0; sFrame.flagFSEQ = wrData.flagFSEQ; sFrame.lenData = wrData.numPairs.Length; sFrame.strData = new byte[sFrame.lenData]; //sFrame.strData[0] = wrData.flagPoint; //sFrame.strData[1] = wrData.flagAUT; //if (wrData.passwd.Length == 3) //{ // sFrame.strData[2] = wrData.passwd[0]; // sFrame.strData[3] = wrData.passwd[1]; // sFrame.strData[4] = wrData.passwd[2]; //} for (int i = 0; i < wrData.numPairs.Length; i++) { sFrame.strData[i] = wrData.numPairs[i]; } sFrame.isTimeCorrectting = wrData.isTimeCorrecting; break; case 0x09: //strComment += "异常告警"; break; case 0x0a: //strComment += "告警确认"; break; case 0x0f: //strComment += "用户自定义数据"; break; case 0x21: //strComment += "登录"; break; case 0x22: //strComment += "登录退出"; break; case 0x24: //strComment += "心跳检验"; break; default: res = false; //strComment += "未知"; break; } return res; } /* *方法名称:frameParsing *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:string pack 帧原始串, * ref struFrame sFrame 保存帧内容的结构 *返回描述:true 成功,false 失败 *功能描述:根据帧原始串,转换为帧内容,存入结构中 */ public static bool frameParsing(byte[] pack, ref struFrame sFrame) { sFrame.flagDTN = (byte)pack[1]; sFrame.addrDNL = new byte[2]; sFrame.addrDNL[0] = (byte)pack[2]; sFrame.addrDNL[1] = (byte)pack[3]; sFrame.flagMSTA = (byte)((byte)0x3f & (byte)pack[4]); sFrame.flagISEQ = (byte)((byte)pack[5] >> 5); sFrame.flagFSEQ = (byte)(((byte)pack[4] >> 6) | (byte)((((byte)pack[5] & 0x1f)) << 2)); sFrame.flagCtrl = (byte)pack[7]; sFrame.flagCtrlD = (byte)(pack[7] >> 7); sFrame.flagCtrlE = (byte)(pack[7] >> 6 & 1); sFrame.flagCtrlF = (byte)(pack[7] & 0x3f); sFrame.lenData = 256 * Convert.ToInt32(pack[8]) + Convert.ToInt32(pack[9]); //sFrame.strData = pack.Substring(10, sFrame.lenData); sFrame.strData = new byte[sFrame.lenData]; for (int i = 0; i < sFrame.lenData; i++) { sFrame.strData[i] = pack[10 + i]; } return true; } /* *方法名称:frameCommenting *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:ref struFrame sFrame 保存帧内容的结构, * ref string strComment 描述字符串 *返回描述:void *功能描述:根据帧参数值,转换为语言描述 */ public static void frameCommenting(ref struFrame sFrame, ref string strComment) { strComment = ""; switch (sFrame.flagCtrlF) { case 0x00: strComment += "中继"; break; case 0x01: strComment += "读当前数据"; break; case 0x02: strComment += "读任务数据"; break; case 0x03: strComment += "主动上传数据"; break; case 0x04: strComment += "读编程日志"; break; case 0x07: strComment += "实时写对象参数"; break; case 0x08: strComment += "写对象参数"; break; case 0x09: strComment += "异常告警"; break; case 0x0a: strComment += "告警确认"; break; case 0x0f: strComment += "用户自定义数据"; break; case 0x21: strComment += "登录"; break; case 0x22: strComment += "登录退出"; break; case 0x24: strComment += "心跳检验"; break; default: strComment += "未知类型"; break; } switch (sFrame.flagCtrlD) { case 1: strComment += "应答帧"; break; case 0: strComment += "请求帧"; break; default: break; } strComment += " "; } /* *方法名称:frameChecking *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:ref struFrame sFrame 保存帧内容的结构 *返回描述:true 成功,false 失败 *功能描述:根据帧内容检查 */ public static bool frameChecking(ref struFrame sFrame) { bool res = false; //业务包 if (sFrame.tName.Length == 5) { //检查编号一致 if (sFrame.tName[0] == sFrame.flagDTN && sFrame.tName.Substring(1, 4) == (sFrame.addrDNL[0] * 0x100 + sFrame.addrDNL[1]).ToString("X4") ) res = true; } //登录包 else if (sFrame.tName.Length != 5 && sFrame.flagCtrlF == 0x21) { res = true; } return res; } /* *方法名称:frameRespPacking *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:ref struFrame sFrame 保存帧内容的结构 * ref string strRespFramePack 响应字符串 *返回描述:true 成功,false 失败 *功能描述:制作帧响应包 */ public static bool framePacking(ref struFrame sFrame, ref byte[] strRespFramePack)//???????????????????????? { bool res = false; //request resp strRespFramePack = new byte[12 + sFrame.lenData]; //string strResp = ""; strRespFramePack[0] = 0x68; strRespFramePack[1] = sFrame.flagDTN; strRespFramePack[2] = sFrame.addrDNL[0]; strRespFramePack[3] = sFrame.addrDNL[1]; //strRespFramePack[3] = Convert.ToByte(((int)(sFrame.addrDNL[1])).ToString(),16); strRespFramePack[4] = (byte)(sFrame.flagMSTA | (sFrame.flagFSEQ & 0x3) << 6); strRespFramePack[5] = (byte)(sFrame.flagFSEQ >> 2 | (sFrame.flagISEQ << 5)); strRespFramePack[6] = 0x68; //临时措施,有功16进制数据 if (sFrame.flagCtrl == 0x03/*sFrame.flagCtrl == 0xaa || sFrame.flagCtrl == 0x84 || sFrame.flagCtrl == 0x85*/) { strRespFramePack[7] = sFrame.flagCtrl; } else { strRespFramePack[7] = (byte)(sFrame.flagCtrlF | (sFrame.flagCtrlE << 6) | (sFrame.flagCtrlD << 7)); } if (sFrame.lenData <= 0xffff && sFrame.lenData >= 0) { if (sFrame.lenData == sFrame.strData.Length) { strRespFramePack[8] = (byte)(sFrame.lenData / 0x100); strRespFramePack[9] = (byte)(sFrame.lenData % 0x100); for (int j = 0; j < sFrame.strData.Length; j++) { strRespFramePack[10 + j] = (byte)sFrame.strData[j]; } //int sum = 0; //for (int i = 0; i < strRespFramePack.Length - 2; i++) //{ // sum += (byte)strRespFramePack[i]; //} //byte CS = (byte)(sum % 0x100); byte CS = (byte)countCS(strRespFramePack, 0, strRespFramePack.Length - 2); strRespFramePack[strRespFramePack.Length - 2] = CS; strRespFramePack[strRespFramePack.Length - 1] = 0x16; res = true; } } //frame self return res; } /* *方法名称:frameCopy *9韩荣伟 *创建时间:2010-10-30 *参数描述:ref struFrame sFrame 保存接收帧内容的结构 * ref struFrame sRespFrame 保存响应帧内容的结构 *返回描述:void *功能描述:复制接收帧结构到响应帧结构 */ public static void frameCopy(ref struFrame sFrame, ref struFrame sRespFrame) //public static void frameCopy(struFrame sFrame, struFrame sRespFrame) { //request resp sRespFrame.flagDTN = sFrame.flagDTN; if (sRespFrame.addrDNL == null) { sRespFrame.addrDNL = new byte[2]; } sRespFrame.addrDNL[0] = sFrame.addrDNL[0]; sRespFrame.addrDNL[1] = sFrame.addrDNL[1]; sRespFrame.flagMSTA = sFrame.flagMSTA; sRespFrame.flagISEQ = sFrame.flagISEQ; sRespFrame.flagFSEQ = sFrame.flagFSEQ; sRespFrame.flagCtrl = sFrame.flagCtrl; sRespFrame.flagCtrlD = sFrame.flagCtrlD; sRespFrame.flagCtrlE = sFrame.flagCtrlE; sRespFrame.flagCtrlF = sFrame.flagCtrlF; sRespFrame.lenData = sFrame.lenData; sRespFrame.strData = new byte[sFrame.strData.Length]; for (int i = 0; i < sFrame.strData.Length; i++) { sRespFrame.strData[i] = sFrame.strData[i]; } } /* *方法名称:FindPackFromBuff *创建人:韩荣伟 *创建时间:2010-10-30 *参数描述:ref string buff 取帧的缓存字符串 *返回描述:帧字符串 *功能描述:从缓存字符串取帧 */ public static byte[] FindPackFromBuff(ref byte[] buff) { byte[] res = { }; int ind = -1; for (int i = 0; i < buff.Length; i++) { if (buff[i] == 0x68) { ind = i; break; } } if (ind == -1) { buff = new byte[0]; return res; } //字符串字符位置 //第一个68H位置 int indF68H1 = ind; //第二个68H位置 int indF68H2 = indF68H1 + 6; //长度位置 int indLEN = indF68H1 + 8; //CS位置 int indCS = 0; //16H位置 int indF16H = 0; //帧长度 int lenPack = 0; while (buff.Length >= 12 && indF68H2 < buff.Length) { res = new byte[0]; if (buff[indF68H1] == 0x68 && buff[indF68H2] == 0x68) { //get length if ((indLEN + 2) < buff.Length) { int len = 256 * Convert.ToInt32(buff[indLEN]) + Convert.ToInt32(buff[indLEN + 1]); //计算 结束符 0x16 位置 indF16H = indF68H1 + 11 + len; //计算 校验和位置 indCS = indF16H - 1; //get end flag if (indF16H < buff.Length) { if (buff[indF16H] == 0x16) { //CS 检查 int CSValue = Convert.ToInt32((byte)buff[indCS]); lenPack = indF16H + 1 - indF68H1; //int sum = 0; //for (int i = 0; i < lenPack - 2; i++)////////////////////// //{ // sum += Convert.ToInt32(buff[indF68H1 + i]); //} //sum %= 0x100; int sum = countCS(buff, indF68H1, lenPack - 2); if (sum == CSValue) { res = new byte[lenPack]; for (int j = 0; j < lenPack; j++) { res[j] = buff[indF68H1 + j]; } //buff.CopyTo(Substring(indF68H1, lenPack); //buff.Remove(0, indF68H1 + lenPack); int newPosition = indF68H1 + lenPack; byte[] tmp = new byte[buff.Length - newPosition]; for (int n = 0; n < buff.Length - newPosition; n++) { tmp[n] = buff[n + newPosition]; } buff = tmp;//.Substring(newPosition, buff.Length - newPosition); return res; } else { //ind++, continue } } else { //ind++, continue } } else { break; } } else { break; } } else { //ind++, continue } ind++; indF68H1 = ind; indF68H2 = indF68H1 + 6; indLEN = indF68H1 + 8; indCS = 0; indF16H = 0; lenPack = 0; } return res; } } }