You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

653 lines
23 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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