1710 lines
66 KiB
C#
1710 lines
66 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Net.Sockets;
|
||
using System.Net;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using static System.Net.WebRequestMethods;
|
||
using System.Runtime.InteropServices;
|
||
|
||
namespace UdpServerCMD
|
||
{
|
||
internal class Program
|
||
{
|
||
/// <summary>
|
||
/// 基数【前置位设备数据总数和】
|
||
/// </summary>
|
||
//public static int baseNum = 0;
|
||
public static int length = 0;//接收数据长度
|
||
|
||
/// <summary>
|
||
/// 在线用户列表
|
||
/// </summary>
|
||
public static List<string> idOnLine = new List<string>();
|
||
|
||
/// <summary>
|
||
/// 存储IP及Socket--便于服务器与指定客户端通信
|
||
/// </summary>
|
||
public static Dictionary<string, Socket> OnLineDic = new Dictionary<string, Socket>();
|
||
|
||
public static Socket udpServer;//udp服务器
|
||
public static bool memberReply;//是否回复消息
|
||
public static TypeFunctionCode LastType = TypeFunctionCode.默认;
|
||
|
||
public static int COMPort = 7000;//端口号
|
||
public static string IP1 = "172.16.1.49";//连接IP
|
||
public static EndPoint serverEnd; //服务端
|
||
public static IPEndPoint ipEnd; //发送消息服务端
|
||
public static Socket socket; //目标socket
|
||
public static Thread connectThread; //连接线程
|
||
public static byte[] sendData;//发送的数据
|
||
|
||
|
||
static log4net.ILog log;
|
||
static void Main(string[] args)
|
||
{
|
||
//初始化日志
|
||
log4net.Config.XmlConfigurator.Configure();
|
||
log = log4net.LogManager.GetLogger("loginfo");
|
||
//InitSocket();
|
||
init();
|
||
Console.ReadKey();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送接口初始化
|
||
/// </summary>
|
||
public static void InitSocket(EndPoint endP)
|
||
{
|
||
try
|
||
{
|
||
//定义连接的服务器ip和端口,可以是本机ip,局域网,互联网
|
||
//ipEnd = new IPEndPoint(IPAddress.Parse(IP1), COMPort);
|
||
ipEnd = (IPEndPoint)endP;
|
||
//定义套接字类型,在主线程中定义
|
||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||
//定义服务端
|
||
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
|
||
serverEnd = (EndPoint)sender;
|
||
//print("waiting for sending UDP dgram");
|
||
|
||
//建立初始连接,这句非常重要,第一次连接初始化了serverEnd后面才能收到消息
|
||
//SocketSend("connection-successful signal");
|
||
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
|
||
Console.WriteLine("发送初始化:" + e.Message);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送数据
|
||
/// </summary>
|
||
/// <param name="sendStr"></param>
|
||
public static void SocketSend(string sendStr)
|
||
{
|
||
//清空发送缓存
|
||
sendData = new byte[1024 * 1024 * 2];
|
||
//数据类型转换
|
||
//sendData = Encoding.Default.GetBytes(sendStr);
|
||
|
||
StringBuilder stringBuilder = new StringBuilder("");
|
||
for (int i = 0; i < sendStr.Length; i++)
|
||
{
|
||
if (i != 0 && i % 2 != 0) stringBuilder.Append(sendStr[i] + " ");
|
||
else stringBuilder.Append(sendStr[i]);
|
||
}
|
||
log.Info("发送:" + stringBuilder);
|
||
|
||
sendData = hexStringToByteArray(sendStr);
|
||
|
||
//发送给指定服务端
|
||
socket.SendTo(sendData, sendData.Length, SocketFlags.None, ipEnd);
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 连接关闭
|
||
/// </summary>
|
||
public static void SocketQuit()
|
||
{
|
||
//关闭线程
|
||
if (connectThread != null)
|
||
{
|
||
connectThread.Interrupt();
|
||
connectThread.Abort();
|
||
}
|
||
//最后关闭socket
|
||
if (socket != null)
|
||
socket.Close();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 接收接口初始化
|
||
/// </summary>
|
||
public static void init()
|
||
{
|
||
try
|
||
{
|
||
//var IP = "111.229.30.246";
|
||
var IP = "172.17.0.9";
|
||
//var IP = "172.16.1.49";
|
||
var Port = 12301;
|
||
|
||
//建立udp服务器,参数2:udp协议以数据报的方式传输,参数3:UDP协议
|
||
udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||
//为服务器绑定IP
|
||
IPAddress ip = IPAddress.Parse(IP);
|
||
EndPoint ep = new IPEndPoint(ip, Port);
|
||
udpServer.Bind(ep);
|
||
//接收数据
|
||
EndPoint endP = new IPEndPoint(IPAddress.Any, 0);
|
||
|
||
string message;
|
||
byte[] data = new byte[1024 * 1024 * 2];
|
||
length = 0;
|
||
//把数据的来源放到第二个参数上
|
||
while (true)
|
||
{
|
||
length = udpServer.ReceiveFrom(data, ref endP);
|
||
//message = Encoding.Default.GetString(data, 0, length);
|
||
message = byteArrayToHexString(data, length);
|
||
log.Info("接收:" + message);
|
||
message = message.Replace(" ", "");
|
||
InitSocket(endP);
|
||
Console.WriteLine("地址:" + endP.ToString() + "\n");
|
||
int baseNum = 0;//基数【前置位设备数据总数和】
|
||
var LoginFrame = message[20].ToString() + message[21].ToString();//功能码C
|
||
JudgmentFunctionCode(LoginFrame, message, baseNum);
|
||
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
|
||
Console.WriteLine("接收初始化:" + e.Message);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// byte[]直接转Float**
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <returns></returns>
|
||
public static float byteToFloat(string message)
|
||
{
|
||
byte[] bFxianOrg = new byte[4];
|
||
var a = stringToByteArray(message, Encoding.Default);
|
||
StringBuilder zz = new StringBuilder("");
|
||
StringBuilder _zz = new StringBuilder("");
|
||
string[] s = new string[4];
|
||
int x = 0;
|
||
for (int i = 0; i < a.Length; i++)
|
||
{
|
||
if (x != 0 && i % 2 == 0)
|
||
{
|
||
zz.Append(int.Parse(hexStr2Str(_zz.ToString())).ToString()).Append("-");
|
||
_zz.Clear();
|
||
x = 0;
|
||
}
|
||
_zz.Append(((char)a[i]).ToString());
|
||
if (i == a.Length - 1)
|
||
{
|
||
zz.Append(int.Parse(hexStr2Str(_zz.ToString())).ToString()).Append("-");
|
||
_zz.Clear();
|
||
}
|
||
x++;
|
||
}
|
||
s = zz.ToString().Split('-');
|
||
byte a0 = byte.Parse(s[0].ToString());
|
||
byte a1 = byte.Parse(s[1].ToString());
|
||
byte a2 = byte.Parse(s[2].ToString());
|
||
byte a3 = byte.Parse(s[3].ToString());
|
||
bFxianOrg = new byte[4] { a0, a1, a2, a3 };
|
||
var b = BitConverter.ToSingle(bFxianOrg, 0);
|
||
return b;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 16进制转字符串(十进制)**
|
||
/// </summary>
|
||
/// <param name="hexStr"></param>
|
||
/// <returns></returns>
|
||
public static string hexStr2Str(String hexStr)
|
||
{
|
||
String str = "0123456789ABCDEF";
|
||
char[] hexs = hexStr.ToCharArray();
|
||
byte[] bytes = new byte[hexStr.Length / 2];
|
||
int n;
|
||
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
n = str.IndexOf(hexs[2 * i]) * 16;
|
||
n += str.IndexOf(hexs[2 * i + 1]);
|
||
bytes[i] = (byte)(n & 0xff);
|
||
}
|
||
StringBuilder stringBuilder = new StringBuilder("");
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
stringBuilder.Append(bytes[i]);
|
||
}
|
||
return (stringBuilder.ToString());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 16进制转ASCII码**
|
||
/// </summary>
|
||
/// <param name="hexStr">16进制字符</param>
|
||
/// <returns></returns>
|
||
public static StringBuilder hexToASCII(string hexStr)
|
||
{
|
||
String str = "0123456789ABCDEF";
|
||
char[] hexs = hexStr.ToCharArray();
|
||
byte[] bytes = new byte[hexStr.Length / 2];
|
||
int n;
|
||
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
n = str.IndexOf(hexs[2 * i]) * 16;
|
||
n += str.IndexOf(hexs[2 * i + 1]);
|
||
bytes[i] = (byte)(n & 0xff);
|
||
}
|
||
StringBuilder VersionNumber = new StringBuilder("");
|
||
for (int i = 0; i < bytes.Length; i++)
|
||
{
|
||
VersionNumber.Append((char)bytes[i]);
|
||
}
|
||
return VersionNumber;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取高四位**
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static int getHeight4(byte data)
|
||
{
|
||
int height;
|
||
height = ((data & 0xf0) >> 4);
|
||
return height;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取低四位**
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static int getLow4(byte data)
|
||
{
|
||
int low;
|
||
low = (data & 0x0f);
|
||
return low;
|
||
}
|
||
|
||
/// <summary>
|
||
/// //16进制转2进制
|
||
/// </summary>
|
||
/// <param name="hexString"></param>
|
||
/// <returns></returns>
|
||
public static string HexString2BinString(string hexString)
|
||
{
|
||
try
|
||
{
|
||
string result = string.Empty;
|
||
foreach (char c in hexString)
|
||
{
|
||
int v = Convert.ToInt32(c.ToString(), 16);
|
||
int v2 = int.Parse(Convert.ToString(v, 2));
|
||
// 去掉格式串中的空格,即可去掉每个4位二进制数之间的空格,
|
||
result += string.Format("{0:d4} ", v2);
|
||
}
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine(ex.Message);
|
||
throw;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 二进制算术累加**【计算校验位/码CS】
|
||
/// </summary>
|
||
/// <param name="j">起始</param>
|
||
/// <param name="k">终止</param>
|
||
/// <param name="message">“控制位”“数据位”所有数据</param>
|
||
/// <returns></returns>
|
||
public static string binAccumulation(int j, int k, string message)
|
||
{
|
||
StringBuilder parityBitCS = new StringBuilder("");//校验位CS --“控制位”、“数据位”的各字节进行二进制算术累加,不计超过 0xFF 的溢出值
|
||
long _parityBitCS = 0;
|
||
int x = 0;
|
||
for (int i = j; i <= k; i++)
|
||
{
|
||
if (x % 2 == 0 && x != 0)
|
||
{
|
||
var a = hexStr2Str(parityBitCS.ToString());
|
||
_parityBitCS += int.Parse(a);
|
||
parityBitCS.Clear();
|
||
x = 0;
|
||
}
|
||
parityBitCS.Append(message[i]);
|
||
if (i == k)
|
||
{
|
||
var a = hexStr2Str(parityBitCS.ToString());
|
||
_parityBitCS += int.Parse(a);
|
||
}
|
||
x++;
|
||
}
|
||
_parityBitCS = _parityBitCS & Convert.ToInt64("FF", 16);
|
||
return _parityBitCS.ToString("X2");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 每8bit高低位互换
|
||
/// </summary>
|
||
/// <param name="j">起始</param>
|
||
/// <param name="k">终止</param>
|
||
/// <param name="message">需要转换的16进制数据</param>
|
||
/// <returns>新的16进制数据</returns>
|
||
public static string interconvert(int j, int k, string message, bool exchange = true)
|
||
{
|
||
StringBuilder parityBitCS = new StringBuilder("");//互换后的值
|
||
//StringBuilder _parityBitH = new StringBuilder("");//高字节
|
||
//StringBuilder _parityBitL = new StringBuilder("");//低字节
|
||
//StringBuilder _parityBit = new StringBuilder("");//记录当前字节
|
||
//int x = 0;
|
||
//for (int i = j; i <= k; i++)//??
|
||
//{
|
||
// if (x == 4)
|
||
// {
|
||
// _parityBitL.Append(_parityBit);//记录低字节
|
||
// parityBitCS.Append(_parityBitL).Append(_parityBitH);//低字节--高字节
|
||
// _parityBitL.Clear();//清空低字节
|
||
// _parityBitH.Clear();//清空高字节
|
||
// _parityBit.Clear();
|
||
// x = 0;
|
||
// }
|
||
// else if (x == 2)//记录高字节
|
||
// {
|
||
// _parityBitH.Append(_parityBit);
|
||
// _parityBit.Clear();
|
||
// }
|
||
// _parityBit.Append(message[i]);
|
||
// if (i == k)
|
||
// {
|
||
// _parityBitL.Append(_parityBit);//记录低字节
|
||
// parityBitCS.Append(_parityBitL).Append(_parityBitH);//低字节--高字节
|
||
// }
|
||
// x++;
|
||
//}
|
||
string[] strings = new string[4] { message[0].ToString() + message[1].ToString(), message[2].ToString() + message[3].ToString(), message[4].ToString() + message[5].ToString(), message[6].ToString() + message[7].ToString() };
|
||
for (int i = strings.Length - 1; i >= 0; i--)
|
||
{
|
||
parityBitCS.Append(strings[i].ToString());
|
||
}
|
||
return Convert.ToInt32(parityBitCS.ToString(), 16).ToString();
|
||
}
|
||
|
||
|
||
#region 暂存
|
||
|
||
/// <summary>
|
||
/// byte数组转string
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static string byteArrayToString(byte[] data, Encoding encoding)
|
||
{
|
||
return encoding.GetString(data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// string转 byte数组
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static byte[] stringToByteArray(string data, Encoding encoding)
|
||
{
|
||
return encoding.GetBytes(data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// byte数组转16进制字符串
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static string byteArrayToHexString(byte[] data, int length = 0)
|
||
{
|
||
int dataLength = 0;
|
||
if (length != 0) dataLength = length;
|
||
else dataLength = data.Length;
|
||
|
||
StringBuilder builder = new StringBuilder();
|
||
for (int i = 0; i < dataLength; i++)
|
||
{
|
||
builder.Append(string.Format("{0:X2} ", data[i]));
|
||
}
|
||
return builder.ToString().Trim();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 16进制字符串转byte数组
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static byte[] hexStringToByteArray(string data)
|
||
{
|
||
//string[] chars = data.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||
List<string> chars = new List<string>();
|
||
for (int i = 0; i < data.Length; i++)
|
||
{
|
||
chars.Add(data[i].ToString());
|
||
}
|
||
//byte[] _returnBytes = new byte[chars.Count];
|
||
byte[] returnBytes = new byte[chars.Count/2];
|
||
//逐个字符变为16进制字节数据
|
||
for (int i = 0; i < chars.Count; i++)
|
||
{
|
||
try
|
||
{
|
||
if (i % 2 == 0)
|
||
{
|
||
returnBytes[i/2] = (byte)(Convert.ToByte(chars[i].ToString() + chars[i + 1].ToString(), 16));
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
//var a = hexStr2Str(chars[i]);
|
||
//short b = short.Parse(a);
|
||
//byte c = (byte)(b % 256);
|
||
//returnBytes[i] = c;
|
||
Console.WriteLine(e.Message);
|
||
}
|
||
|
||
}
|
||
return returnBytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// byte数组转10进制字符串
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static string byteArrayToDecString(byte[] data)
|
||
{
|
||
StringBuilder builder = new StringBuilder();
|
||
for (int i = 0; i < data.Length; i++)
|
||
{
|
||
builder.Append(data[i] + " ");
|
||
}
|
||
return builder.ToString().Trim();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 10进制字符串转byte数组
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static byte[] decStringToByteArray(string data)
|
||
{
|
||
string[] chars = data.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||
byte[] returnBytes = new byte[chars.Length];
|
||
//逐个字符变为10进制字节数据
|
||
for (int i = 0; i < chars.Length; i++)
|
||
{
|
||
returnBytes[i] = Convert.ToByte(chars[i], 10);
|
||
}
|
||
return returnBytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// byte数组转八进制字符串
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static string byteArrayToOtcString(byte[] data)
|
||
{
|
||
StringBuilder builder = new StringBuilder();
|
||
for (int i = 0; i < data.Length; i++)
|
||
{
|
||
builder.Append(Convert.ToString(data[i], 8) + " ");
|
||
}
|
||
return builder.ToString().Trim();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 八进制字符串转byte数组
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static byte[] otcStringToByteArray(string data)
|
||
{
|
||
string[] chars = data.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||
byte[] returnBytes = new byte[chars.Length];
|
||
//逐个字符变为8进制字节数据
|
||
for (int i = 0; i < chars.Length; i++)
|
||
{
|
||
returnBytes[i] = Convert.ToByte(chars[i], 8);
|
||
}
|
||
return returnBytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 二进制字符串转byte数组
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static byte[] binStringToByteArray(string data)
|
||
{
|
||
string[] chars = data.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||
byte[] returnBytes = new byte[chars.Length];
|
||
//逐个字符变为2进制字节数据
|
||
for (int i = 0; i < chars.Length; i++)
|
||
{
|
||
returnBytes[i] = Convert.ToByte(chars[i], 2);
|
||
}
|
||
return returnBytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// byte数组转二进制字符串
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static string byteArrayToBinString(byte[] data)
|
||
{
|
||
StringBuilder builder = new StringBuilder();
|
||
for (int i = 0; i < data.Length; i++)
|
||
{
|
||
builder.Append(Convert.ToString(data[i], 2) + " ");
|
||
}
|
||
return builder.ToString().Trim();
|
||
}
|
||
#endregion
|
||
|
||
|
||
#region 正向解析
|
||
|
||
/// <summary>
|
||
/// 登录帧解析
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
public static void LoginFrameAnalysis(string message, IPEndPoint ipEnd, Socket socket)
|
||
{
|
||
#region 登录帧解析
|
||
|
||
StringBuilder DataLength = new StringBuilder("");//数据部长度L
|
||
for (int i = 4; i <= 7; i++)
|
||
{
|
||
DataLength.Append(message[i]);
|
||
}
|
||
int.Parse(hexStr2Str(DataLength.ToString()));
|
||
Console.WriteLine("数据部长度:" + int.Parse(hexStr2Str(DataLength.ToString())));
|
||
|
||
|
||
StringBuilder SimID = new StringBuilder(""); //客户端地址A -- 11位时编码需在最后一字节低四位补 F
|
||
if (message[19].ToString() == "F")
|
||
{
|
||
for (int i = 8; i < 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 8; i <= 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
Console.WriteLine("客户端地址:" + SimID);
|
||
|
||
|
||
StringBuilder _voltage = new StringBuilder("");//电压 --缩小10 倍为实际数值
|
||
float voltage;//电压
|
||
for (int i = 22; i <= 23; i++)
|
||
{
|
||
_voltage.Append(message[i]);
|
||
}
|
||
voltage = float.Parse(_voltage.ToString()) / 10;
|
||
Console.WriteLine("电压:" + voltage);
|
||
|
||
|
||
StringBuilder _signal = new StringBuilder("");//信号 --信号为整数
|
||
int signal;
|
||
for (int i = 24; i <= 25; i++)
|
||
{
|
||
_signal.Append(message[i]);
|
||
}
|
||
signal = int.Parse(_signal.ToString());
|
||
Console.WriteLine("信号:" + signal);
|
||
|
||
|
||
StringBuilder date = new StringBuilder("20");//日期 --(BCD 码)
|
||
for (int i = 26; i <= 37; i++)
|
||
{
|
||
if (i == 27 || i == 29) date.Append(message[i] + "-");
|
||
else if (i == 31) date.Append(message[i] + " ");
|
||
else if (i == 33 || i == 35) date.Append(message[i] + ":");
|
||
else date.Append(message[i]);
|
||
}
|
||
Console.WriteLine("日期:" + date);
|
||
|
||
|
||
StringBuilder workPattern = new StringBuilder("");//工作模式 --0x00 定时开机,0x01 实时在线
|
||
for (int i = 38; i <= 39; i++)
|
||
{
|
||
workPattern.Append(message[i]);
|
||
}
|
||
switch ((TypeworkPattern)int.Parse(workPattern.ToString()))
|
||
{
|
||
case TypeworkPattern.定时开机:
|
||
Console.WriteLine(TypeworkPattern.定时开机);
|
||
break;
|
||
case TypeworkPattern.实时在线:
|
||
Console.WriteLine(TypeworkPattern.实时在线);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
|
||
StringBuilder _meterNumber = new StringBuilder("");//仪表数量
|
||
StringBuilder meterNumber = new StringBuilder("");//仪表数量
|
||
for (int i = 40; i <= 41; i++)
|
||
{
|
||
_meterNumber.Append(message[i]);
|
||
}
|
||
meterNumber.Append(int.Parse(_meterNumber.ToString()).ToString() + "台");
|
||
Console.WriteLine("仪表数量:" + meterNumber);
|
||
|
||
|
||
StringBuilder positionNumber = new StringBuilder("");//位置号 --取低 4 位为实际值
|
||
for (int i = 42; i <= 43; i++)
|
||
{
|
||
//if (i == 42) continue;//取低 4 位为实际值
|
||
positionNumber.Append(message[i]);
|
||
}
|
||
Console.WriteLine("位置号:" + getLow4(byte.Parse(hexStr2Str(positionNumber.ToString()))) + "号");
|
||
|
||
|
||
StringBuilder phenotype = new StringBuilder("");//表型
|
||
for (int i = 44; i <= 45; i++)
|
||
{
|
||
phenotype.Append(message[i]);
|
||
}
|
||
typePheno(phenotype);
|
||
|
||
|
||
StringBuilder versionMumber = new StringBuilder("");//版本号 --开始字节4A
|
||
for (int i = 46; i <= 87; i++)
|
||
{
|
||
if (i == 46 || i == 47) continue;
|
||
versionMumber.Append(message[i]);
|
||
}
|
||
versionMumber = hexToASCII(versionMumber.ToString());
|
||
Console.WriteLine("版本号" + versionMumber);
|
||
|
||
|
||
StringBuilder reportingCycle = new StringBuilder("");//上报周期 --开始字节4B。115 :15分钟 ,130:30 分钟,24:24小时
|
||
for (int i = 88; i <= 91; i++)
|
||
{
|
||
if (i == 88 || i == 89) continue;
|
||
reportingCycle.Append(message[i]);
|
||
}
|
||
if (int.Parse(hexStr2Str(reportingCycle.ToString())) != 24)
|
||
{
|
||
var v = new StringBuilder(hexStr2Str(reportingCycle.ToString()));
|
||
v.Remove(0, 2);
|
||
Console.WriteLine(v + "h");
|
||
}
|
||
else if (int.Parse(hexStr2Str(reportingCycle.ToString())) == 24)
|
||
{
|
||
Console.WriteLine(int.Parse(hexStr2Str(reportingCycle.ToString())) + "h");
|
||
}
|
||
|
||
|
||
StringBuilder acquisitionCycle = new StringBuilder("");//采集周期 --开始字节4C。高字节在前,单位:秒
|
||
for (int i = 92; i <= 97; i++)
|
||
{
|
||
if (i == 92 || i == 93) continue;
|
||
acquisitionCycle.Append(message[i]);
|
||
}
|
||
Convert.ToInt64(acquisitionCycle.ToString(), 16);
|
||
Console.WriteLine("采集周期:" + Convert.ToInt64(acquisitionCycle.ToString(), 16) / 60 + "分钟");
|
||
|
||
|
||
StringBuilder factoryCode = new StringBuilder("");//出厂编码 --开始字节4D。ASCII码
|
||
for (int i = 98; i <= 127; i++)
|
||
{
|
||
if (i == 98 || i == 99) continue;
|
||
factoryCode.Append(message[i]);
|
||
}
|
||
hexToASCII(factoryCode.ToString());
|
||
Console.WriteLine("出厂编码:" + hexToASCII(factoryCode.ToString()));
|
||
|
||
|
||
StringBuilder retain = new StringBuilder("");//保留 --开始字节4F。不做处理
|
||
for (int i = 128; i <= 145; i++)
|
||
{
|
||
if (i == 128 || i == 129) continue;
|
||
retain.Append(message[i]);
|
||
}
|
||
|
||
|
||
Console.WriteLine("校验位CS:" + binAccumulation(4, 145, message));
|
||
|
||
|
||
|
||
#endregion
|
||
longinDecompilation(SimID, ipEnd, socket);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数据帧1解析
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void dataFramesAnalysis(string message, string code, int baseNum)
|
||
{
|
||
basicsAnalysis(message);
|
||
Isgo(message, baseNum);
|
||
sendClock(message);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 时钟解析
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
public static void clockAnalysis(string message, IPEndPoint ipEnd)
|
||
{
|
||
StringBuilder DataLength = new StringBuilder("");//数据部长度L
|
||
for (int i = 4; i <= 7; i++)
|
||
{
|
||
DataLength.Append(message[i]);
|
||
}
|
||
int.Parse(hexStr2Str(DataLength.ToString()));
|
||
Console.WriteLine("数据部长度:" + int.Parse(hexStr2Str(DataLength.ToString())));
|
||
|
||
|
||
StringBuilder SimID = new StringBuilder(""); //客户端地址A -- 11位时编码需在最后一字节低四位补 F
|
||
if (message[19].ToString() == "F")
|
||
{
|
||
for (int i = 8; i < 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 8; i <= 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
Console.WriteLine("客户端地址:" + SimID);
|
||
|
||
StringBuilder _clock = new StringBuilder("");
|
||
StringBuilder clock = new StringBuilder("");//时钟 --年只取后两位
|
||
for (int i = 22; i <= 33; i++)
|
||
{
|
||
_clock.Append(message[i]);
|
||
}
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
if (i == 0)
|
||
{
|
||
clock.Append(hexStr2Str(_clock.ToString()[0].ToString() + _clock.ToString()[1].ToString()));
|
||
clock.Append("-");
|
||
}
|
||
else
|
||
{
|
||
clock.Append(hexStr2Str(_clock.ToString()[i * 2].ToString() + _clock.ToString()[i * 2 + 1].ToString()));
|
||
if (i == 1) clock.Append("-");
|
||
else if (i == 2) clock.Append(" ");
|
||
else if (i == 3) clock.Append(":");
|
||
else if (i == 4) clock.Append(":");
|
||
}
|
||
}
|
||
Console.WriteLine("时钟:20" + clock);
|
||
|
||
StringBuilder sig = new StringBuilder("");//有无后续帧标识 --0 无后续帧 1 有后续帧
|
||
for (int i = 34; i <= 35; i++)
|
||
{
|
||
sig.Append(message[i]);
|
||
}
|
||
if (sig.ToString() == "00") Console.WriteLine("无后续帧");
|
||
else Console.WriteLine("有后续帧");
|
||
|
||
StringBuilder parityBitCS = new StringBuilder("");//校验位CS --“控制位”、“数据位”的各字节进行二进制算术累加,不计超过 0xFF 的溢出值
|
||
parityBitCS.Append(binAccumulation(4, 35, message.ToString()));
|
||
Console.WriteLine("校验位CS:" + parityBitCS);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 反编译
|
||
|
||
/// <summary>
|
||
/// 登录帧反编译
|
||
/// </summary>
|
||
/// <param name="SimID">客户端地址A</param>
|
||
public static void longinDecompilation(StringBuilder SimID, IPEndPoint ipEnd, Socket socket)
|
||
{
|
||
if (SimID.Length == 11) SimID.Append("F");
|
||
StringBuilder parityBitCS = new StringBuilder("");
|
||
StringBuilder message = new StringBuilder("403A" + "0009" + SimID + "01" + "00");
|
||
parityBitCS.Append(binAccumulation(4, 23, message.ToString()));
|
||
var a = message.Append(parityBitCS).ToString() + "0D0A";
|
||
SocketSend(a);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数据帧反编译
|
||
/// </summary>
|
||
/// <param name="SimID">sim码</param>
|
||
/// <param name="code">功能码</param>
|
||
/// <param name="versionNum">版本号</param>
|
||
public static void dataFramesDecompilation(StringBuilder SimID, string code, IPEndPoint ipEnd, Socket socket, string versionNum = "01")
|
||
{
|
||
if (SimID.Length == 11) SimID.Append("F");
|
||
StringBuilder parityBitCS = new StringBuilder("");
|
||
StringBuilder message = new StringBuilder("403A" + "000B" + SimID + code + versionNum + "0100");
|
||
parityBitCS.Append(binAccumulation(4, 27, message.ToString()));
|
||
SocketSend(message.Append(parityBitCS) + "0D0A");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送时钟校验
|
||
/// </summary>
|
||
/// <param name="SimID"></param>
|
||
public static void sendClock(string message)
|
||
{
|
||
StringBuilder SimID = new StringBuilder(""); //客户端地址A -- 11位时编码需在最后一字节低四位补 F
|
||
for (int i = 8; i <= 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
StringBuilder parityBitCS = new StringBuilder("");//校验位CS --“控制位”、“数据位”的各字节进行二进制算术累加,不计超过 0xFF 的溢出值
|
||
StringBuilder Clock = new StringBuilder("");//时钟 --年只取后两位
|
||
Clock.Append(getClock());
|
||
StringBuilder sig = new StringBuilder("00");//有无后续帧标识 --0 无后续帧 1 有后续帧
|
||
StringBuilder msg = new StringBuilder("403A" + "000F" + SimID + "05" + Clock + sig);
|
||
parityBitCS.Append(binAccumulation(4, 35, msg.ToString()));
|
||
SocketSend(msg.Append(parityBitCS).ToString() + "0D0A");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前时钟的16进制【年只取后两位】
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static string getClock()
|
||
{
|
||
StringBuilder builder = new StringBuilder("");
|
||
string str = DateTime.Now.ToString();
|
||
string[] strings = str.Split(':', '/', ' ');
|
||
for (int i = 0; i < strings.Length; i++)
|
||
{
|
||
if (strings[i].Length == 1) strings[i] = 0 + strings[i].ToString();
|
||
}
|
||
for (int i = 0; i < strings.Length; i++)
|
||
{
|
||
if (i == 0) builder.Append(int.Parse(strings[i][2].ToString() + strings[i][3].ToString()).ToString("X2").ToString());
|
||
else builder.Append(int.Parse(strings[i]).ToString("X2").ToString());
|
||
}
|
||
return builder.ToString();
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// 基础解析【长度--采集时间】
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
public static void basicsAnalysis(string message)
|
||
{
|
||
#region 长度--采集时间
|
||
|
||
StringBuilder DataLength = new StringBuilder("");//数据部长度L
|
||
for (int i = 4; i <= 7; i++)
|
||
{
|
||
DataLength.Append(message[i]);
|
||
}
|
||
int.Parse(hexStr2Str(DataLength.ToString()));
|
||
Console.WriteLine("数据部长度:" + int.Parse(hexStr2Str(DataLength.ToString())));
|
||
|
||
|
||
StringBuilder SimID = new StringBuilder(""); //客户端地址A -- 11位时编码需在最后一字节低四位补 F
|
||
if (message[19].ToString() == "F")
|
||
{
|
||
for (int i = 8; i < 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 8; i <= 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
Console.WriteLine("客户端地址:" + SimID);
|
||
|
||
|
||
StringBuilder totalFrames = new StringBuilder("");//总帧数
|
||
for (int i = 22; i <= 23; i++)
|
||
{
|
||
totalFrames.Append(message[i]);
|
||
}
|
||
Console.WriteLine("总帧数:" + int.Parse(totalFrames.ToString()));
|
||
|
||
|
||
StringBuilder whichFrame = new StringBuilder("");//第几帧
|
||
for (int i = 24; i <= 25; i++)
|
||
{
|
||
whichFrame.Append(message[i]);
|
||
}
|
||
Console.WriteLine("第几帧:" + int.Parse(whichFrame.ToString()));
|
||
|
||
|
||
StringBuilder currentFrame = new StringBuilder(""); //此帧表数
|
||
for (int i = 26; i <= 27; i++)
|
||
{
|
||
currentFrame.Append(message[i]);
|
||
}
|
||
Console.WriteLine("此帧表数:" + int.Parse(currentFrame.ToString()));
|
||
|
||
#region 暂存
|
||
//StringBuilder platForm = new StringBuilder("");//站号 --十进制减去64 为实际数值
|
||
//for (int i = 28; i <= 29; i++)
|
||
//{
|
||
// platForm.Append(message[i]);
|
||
//}
|
||
//var _platForm = int.Parse(hexStr2Str(platForm.ToString())) - 64;
|
||
//Console.WriteLine("站号:" + _platForm);
|
||
|
||
//StringBuilder phenotype = new StringBuilder("");//表型
|
||
//for (int i = 30; i <= 31; i++)
|
||
//{
|
||
// phenotype.Append(message[i]);
|
||
//}
|
||
//StringBuilder _phenotype = new StringBuilder("");//--表型数字 81 83 84
|
||
////_phenotype.Clear().Append(typePheno(phenotype));
|
||
|
||
|
||
//StringBuilder alarmCode = new StringBuilder("");//报警码
|
||
//for (int i = 32; i <= 33; i++)
|
||
//{
|
||
// alarmCode.Append(message[i]);
|
||
//}
|
||
//typeAlarmcode(alarmCode);
|
||
|
||
|
||
//StringBuilder date = new StringBuilder("20");//采集时间 --(BCD 码)
|
||
//for (int i = 34; i <= 43; i++)
|
||
//{
|
||
// if (i == 35 || i == 37) date.Append(message[i] + "-");
|
||
// else if (i == 39) date.Append(message[i] + " ");
|
||
// else if (i == 41) date.Append(message[i] + ":");
|
||
// else date.Append(message[i]);
|
||
//}
|
||
//Console.WriteLine("采集时间:" + date);
|
||
#endregion
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断后面是否存在仪表数据【有继续】
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// 表型起始位下标 22 + 6 + baseNum + 2
|
||
/// 表型终止位下标 22 + 6 + baseNum + 3
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void Isgo(string message, int baseNum)
|
||
{
|
||
try
|
||
{
|
||
if (message.Length >= 31 + baseNum)
|
||
{
|
||
StringBuilder go = new StringBuilder(message[30 + baseNum].ToString() + message[31 + baseNum].ToString());//表型
|
||
var code = message[20].ToString() + message[21].ToString();//功能码C
|
||
StringBuilder SimID = new StringBuilder(""); //客户端地址A -- 11位时编码需在最后一字节低四位补 F
|
||
if (message[19].ToString() == "F")
|
||
{
|
||
for (int i = 8; i < 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 8; i <= 19; i++)
|
||
{
|
||
SimID.Append(message[i]);
|
||
}
|
||
}
|
||
if (go.ToString() == "84")
|
||
{
|
||
Console.WriteLine();
|
||
phenotype84(message, baseNum);
|
||
dataFramesDecompilation(SimID, code, ipEnd, socket);
|
||
}
|
||
else if ((go.ToString() == "83"))
|
||
{
|
||
Console.WriteLine();
|
||
phenotype83(message, baseNum);
|
||
dataFramesDecompilation(SimID, code, ipEnd, socket);
|
||
}
|
||
else if ((go.ToString() == "81"))
|
||
{
|
||
Console.WriteLine();
|
||
phenotype81(message, baseNum);
|
||
dataFramesDecompilation(SimID, code, ipEnd, socket);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Console.WriteLine(e.Message.ToString());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 0x81、0x83、0x84共用解析【站号、表型 、报警码、采集时间】
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <param name="multiplier">基数(前所有位合计)</param>
|
||
public static void shareAnalysis(string message, int multiplier)
|
||
{
|
||
StringBuilder platForm = new StringBuilder("");//站号 --十进制减去64 为实际数值
|
||
for (int i = 28 + multiplier; i <= 29 + multiplier; i++)
|
||
{
|
||
platForm.Append(message[i]);
|
||
}
|
||
var _platForm = int.Parse(hexStr2Str(platForm.ToString())) - 64;
|
||
Console.WriteLine("站号:" + _platForm);
|
||
|
||
StringBuilder phenotype = new StringBuilder("");//表型
|
||
for (int i = 30 + multiplier; i <= 31 + multiplier; i++)
|
||
{
|
||
phenotype.Append(message[i]);
|
||
}
|
||
StringBuilder _phenotype = new StringBuilder("");//--表型数字 81 83 84
|
||
_phenotype.Clear().Append(typePheno(phenotype));
|
||
|
||
|
||
StringBuilder alarmCode = new StringBuilder("");//报警码
|
||
for (int i = 32 + multiplier; i <= 33 + multiplier; i++)
|
||
{
|
||
alarmCode.Append(message[i]);
|
||
}
|
||
typeAlarmcode(alarmCode);
|
||
|
||
|
||
StringBuilder date = new StringBuilder("20");//采集时间 --(BCD 码)
|
||
for (int i = 34 + multiplier; i <= 43 + multiplier; i++)
|
||
{
|
||
if (i == 35 + multiplier || i == 37 + multiplier) date.Append(message[i] + "-");
|
||
else if (i == 39 + multiplier) date.Append(message[i] + " ");
|
||
else if (i == 41 + multiplier) date.Append(message[i] + ":");
|
||
else date.Append(message[i]);
|
||
}
|
||
Console.WriteLine("采集时间:" + date);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表型81
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void phenotype81(string message, int baseNum)
|
||
{
|
||
int multiplier;//基数(前所有位合计)
|
||
if (baseNum != 0)
|
||
{
|
||
//var multiplier = (whatFrame - 1) * 84;
|
||
multiplier = baseNum;
|
||
baseNum += (68 + 16);
|
||
}
|
||
else
|
||
{
|
||
multiplier = 0;
|
||
baseNum = (68 + 16);
|
||
}
|
||
|
||
shareAnalysis(message, multiplier);
|
||
|
||
StringBuilder validity = new StringBuilder("");//抄表数据有效 --无符号整型,0x26 有效,其他无效
|
||
for (int i = 44 + multiplier; i <= 45 + multiplier; i++)
|
||
{
|
||
validity.Append(message[i]);
|
||
}
|
||
if (validity.ToString() == "26")
|
||
{
|
||
Console.WriteLine("抄表数据有效");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("抄表数据无效");
|
||
}
|
||
|
||
StringBuilder versionNum = new StringBuilder(""); //版本号 --整型
|
||
for (int i = 46 + multiplier; i <= 47 + multiplier; i++)
|
||
{
|
||
versionNum.Append(message[i]);
|
||
}
|
||
Console.WriteLine("版本号:" + int.Parse(versionNum.ToString()));
|
||
|
||
StringBuilder instantaneousFlow = new StringBuilder("");//瞬时流量 --浮点型,缩小 1000 倍为实际值,单位: m3/h
|
||
for (int i = 48 + multiplier; i <= 55 + multiplier; i++)
|
||
{
|
||
instantaneousFlow.Append(message[i]);
|
||
}
|
||
var _instantaneousFlow = byteToFloat(instantaneousFlow.ToString()) / 1000;
|
||
Console.WriteLine("瞬时流量" + _instantaneousFlow.ToString() + "m3/h");
|
||
|
||
StringBuilder _positiveFlow = new StringBuilder("");//累积流量 --带符号整型,低字节在前,高字节在后,缩小 10 倍为实际数值,单位: m3。
|
||
for (int i = 56 + multiplier; i <= 63 + multiplier; i++)
|
||
{
|
||
_positiveFlow.Append(message[i]);
|
||
}
|
||
int positiveFlow = int.Parse(/*hexStr2Str*/(interconvert(56 + multiplier, 63 + multiplier, _positiveFlow.ToString()))) / 10;//???
|
||
Console.WriteLine("累积流量:" + positiveFlow + "m3");
|
||
|
||
StringBuilder waterTemperature = new StringBuilder("");//水温 --浮点型,单位: ℃
|
||
for (int i = 64 + multiplier; i <= 71 + multiplier; i++)
|
||
{
|
||
waterTemperature.Append(message[i]);
|
||
}
|
||
var _waterTemperature = byteToFloat(waterTemperature.ToString());//???
|
||
Console.WriteLine("水温:" + _waterTemperature + "℃");
|
||
|
||
StringBuilder _RunTime = new StringBuilder("");//累积运行时间 --带符号整型,低字节在前,高字节在后,单位: h
|
||
for (int i = 72 + multiplier; i <= 79 + multiplier; i++)
|
||
{
|
||
_RunTime.Append(message[i]);
|
||
}
|
||
int RunTime = int.Parse(/*hexStr2Str*/(interconvert(72 + multiplier, 79 + multiplier, _RunTime.ToString())));//???
|
||
Console.WriteLine("累积运行时间:" + RunTime + "h");
|
||
|
||
StringBuilder _cellVoltage = new StringBuilder("");//电池电压 --浮点型,低字节在前,高字节在后,单位: v。
|
||
for (int i = 80 + multiplier; i <= 87 + multiplier; i++)
|
||
{
|
||
_cellVoltage.Append(message[i]);
|
||
}
|
||
//float cellVoltage = float.Parse(/*hexStr2Str*/(interconvert(80 + multiplier, 87 + multiplier, _cellVoltage.ToString())));
|
||
float cellVoltage = byteToFloat(_cellVoltage.ToString());//???
|
||
Console.WriteLine("电池电压:" + cellVoltage + "v");
|
||
|
||
StringBuilder _pipeSize = new StringBuilder("");//管径 --浮点型,单位: mm
|
||
for (int i = 88 + multiplier; i <= 95 + multiplier; i++)
|
||
{
|
||
_pipeSize.Append(message[i]);
|
||
}
|
||
//float pipeSize = float.Parse(_pipeSize.ToString());
|
||
float pipeSize = byteToFloat(_pipeSize.ToString());//???
|
||
Console.WriteLine("管径:" + pipeSize + "mm");
|
||
|
||
StringBuilder capacity = new StringBuilder("");//量程 --长整型,单位:单位缺失。
|
||
for (int i = 96 + multiplier; i <= 103 + multiplier; i++)
|
||
{
|
||
capacity.Append(message[i]);
|
||
}
|
||
Console.WriteLine("量程:" + interconvert(0, 0, capacity.ToString()));//???
|
||
|
||
StringBuilder dampingFactor = new StringBuilder("");//阻尼系数 --ASCII 码
|
||
for (int i = 104 + multiplier; i <= 105 + multiplier; i++)
|
||
{
|
||
dampingFactor.Append(message[i]);
|
||
}
|
||
//Console.WriteLine("阻尼系数:" + hexToASCII(dampingFactor.ToString()));
|
||
|
||
StringBuilder InstrumentType = new StringBuilder("");//仪表类型
|
||
for (int i = 106 + multiplier; i <= 107 + multiplier; i++)
|
||
{
|
||
InstrumentType.Append(message[i]);
|
||
}
|
||
|
||
StringBuilder diagnose = new StringBuilder("");//诊断代码(仪表故障码) --当设备上报 0x06 故障时,不应再上报其他故障。
|
||
for (int i = 108 + multiplier; i <= 109 + multiplier; i++)
|
||
{
|
||
diagnose.Append(message[i]);
|
||
}
|
||
typeMalfunction(diagnose);
|
||
|
||
//数据校验 --版本号-故障代码
|
||
Console.WriteLine("数据校验:" + binAccumulation(46 + multiplier, 109 + multiplier, message));//版本号--故障码
|
||
Console.WriteLine("校验位CS:" + binAccumulation(4 + multiplier, 111 + multiplier, message));//数据部长度--数据校验
|
||
|
||
Isgo(message, baseNum);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表型83
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void phenotype83(string message, int baseNum)
|
||
{
|
||
int multiplier;
|
||
if (baseNum != 0)
|
||
{
|
||
//var multiplier = (whatFrame - 1) * 84;
|
||
multiplier = baseNum;
|
||
baseNum += (84 + 16);
|
||
}
|
||
else
|
||
{
|
||
multiplier = 0;
|
||
baseNum = (84 + 16);
|
||
}
|
||
|
||
shareAnalysis(message, multiplier);
|
||
|
||
StringBuilder validity = new StringBuilder("");//抄表数据有效 --无符号整型,0x26 有效,其他无效
|
||
for (int i = 44 + multiplier; i <= 45 + multiplier; i++)
|
||
{
|
||
validity.Append(message[i]);
|
||
}
|
||
if (validity.ToString() == "26")
|
||
{
|
||
Console.WriteLine("抄表数据有效");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("抄表数据无效");
|
||
}
|
||
|
||
StringBuilder versionNum = new StringBuilder(""); //版本号 --整型
|
||
for (int i = 46 + multiplier; i <= 47 + multiplier; i++)
|
||
{
|
||
versionNum.Append(message[i]);
|
||
}
|
||
Console.WriteLine("版本号:" + int.Parse(versionNum.ToString()));
|
||
|
||
StringBuilder instantaneousFlow = new StringBuilder("");//瞬时流量 --浮点型,缩小 1000 倍为实际值,单位: m3/h
|
||
for (int i = 48 + multiplier; i <= 55 + multiplier; i++)
|
||
{
|
||
instantaneousFlow.Append(message[i]);
|
||
}
|
||
//Console.WriteLine("瞬时流量" + float.Parse(instantaneousFlow.ToString()) / 1000 + "m3/h");//???
|
||
Console.WriteLine("瞬时流量" + byteToFloat(instantaneousFlow.ToString()) / 1000 + "m3/h");
|
||
|
||
StringBuilder _positiveFlow = new StringBuilder("");//正累积流量 --带符号整型,低字节在前,高字节在后,缩小 10 倍为实际数值,单位: m3
|
||
for (int i = 56 + multiplier; i <= 63 + multiplier; i++)
|
||
{
|
||
_positiveFlow.Append(message[i]);
|
||
}
|
||
//int positiveFlow = int.Parse(hexStr2Str(interconvert(56 + multiplier, 63 + multiplier, _positiveFlow.ToString()))) / 10;//???
|
||
var positiveFlow = float.Parse(/*hexStr2Str*/(interconvert(56 + multiplier, 63 + multiplier, _positiveFlow.ToString()))) / 10;
|
||
Console.WriteLine("正累积流量:" + positiveFlow + "m3");
|
||
|
||
StringBuilder loseFlow = new StringBuilder("");//负累积流量 --BCD 码,缩小10 倍为实际数值,单位:m³
|
||
for (int i = 64 + multiplier; i <= 71 + multiplier; i++)
|
||
{
|
||
loseFlow.Append(message[i]);
|
||
}
|
||
var _loseFlow = float.Parse(loseFlow.ToString()) / 10;
|
||
Console.WriteLine("负累积流量:" + _loseFlow + "m3");
|
||
|
||
StringBuilder loseRunTime = new StringBuilder("");//负累积运行时间 --BCD 码,单位: h。
|
||
for (int i = 72 + multiplier; i <= 79 + multiplier; i++)
|
||
{
|
||
loseRunTime.Append(message[i]);
|
||
}
|
||
var _loseRunTime = int.Parse(loseRunTime.ToString());
|
||
Console.WriteLine("负累积运行时间:" + _loseRunTime + "h");
|
||
|
||
StringBuilder waterTemperature = new StringBuilder("");//水温 --浮点型,单位: ℃
|
||
for (int i = 80 + multiplier; i <= 87 + multiplier; i++)
|
||
{
|
||
waterTemperature.Append(message[i]);
|
||
}
|
||
var _waterTemperature = byteToFloat(waterTemperature.ToString());//???
|
||
Console.WriteLine("水温:" + _waterTemperature + "℃");
|
||
|
||
StringBuilder _RunTime = new StringBuilder("");//累积运行时间 --带符号整型,低字节在前,高字节在后,单位: h
|
||
for (int i = 88 + multiplier; i <= 95 + multiplier; i++)
|
||
{
|
||
_RunTime.Append(message[i]);
|
||
}
|
||
var RunTime = int.Parse(/*hexStr2Str*/(interconvert(88 + multiplier, 95 + multiplier, _RunTime.ToString())));//???
|
||
Console.WriteLine("累积运行时间:" + RunTime + "h");
|
||
|
||
StringBuilder _cellVoltage = new StringBuilder("");//电池电压 --浮点型,低字节在前,高字节在后,单位: v。
|
||
for (int i = 96 + multiplier; i <= 103 + multiplier; i++)
|
||
{
|
||
_cellVoltage.Append(message[i]);
|
||
}
|
||
//float cellVoltage = float.Parse(hexStr2Str(interconvert(96 + multiplier, 103 + multiplier, _cellVoltage.ToString())));//???
|
||
float cellVoltage = byteToFloat(_cellVoltage.ToString());
|
||
Console.WriteLine("电池电压:" + cellVoltage + "v");
|
||
|
||
StringBuilder _pipeSize = new StringBuilder("");//管径 --浮点型,单位: mm
|
||
for (int i = 104 + multiplier; i <= 111 + multiplier; i++)
|
||
{
|
||
_pipeSize.Append(message[i]);
|
||
}
|
||
//float pipeSize = float.Parse(_pipeSize.ToString());//???
|
||
float pipeSize = byteToFloat(_pipeSize.ToString());
|
||
Console.WriteLine("管径:" + pipeSize + "mm");
|
||
|
||
StringBuilder capacity = new StringBuilder("");//量程 --长整型,单位:单位缺失。
|
||
for (int i = 112 + multiplier; i <= 119 + multiplier; i++)
|
||
{
|
||
capacity.Append(message[i]);
|
||
}
|
||
Console.WriteLine("量程:" + interconvert(0, 0, capacity.ToString()));//???
|
||
|
||
StringBuilder dampingFactor = new StringBuilder("");//阻尼系数 --ASCII 码
|
||
for (int i = 120 + multiplier; i <= 121 + multiplier; i++)
|
||
{
|
||
dampingFactor.Append(message[i]);
|
||
}
|
||
//Console.WriteLine("阻尼系数:" + hexToASCII(dampingFactor.ToString()));
|
||
|
||
StringBuilder InstrumentType = new StringBuilder("");//仪表类型
|
||
for (int i = 122 + multiplier; i <= 123 + multiplier; i++)
|
||
{
|
||
InstrumentType.Append(message[i]);
|
||
}
|
||
|
||
StringBuilder diagnose = new StringBuilder("");//诊断代码(仪表故障码) --当设备上报 0x06 故障时,不应再上报其他故障。
|
||
for (int i = 124 + multiplier; i <= 125 + multiplier; i++)
|
||
{
|
||
diagnose.Append(message[i]);
|
||
}
|
||
typeMalfunction(diagnose);
|
||
|
||
//数据校验 --版本号-故障代码
|
||
Console.WriteLine("数据校验:" + binAccumulation(46 + multiplier, 125 + multiplier, message));//版本号--故障码
|
||
Console.WriteLine("校验位CS:" + binAccumulation(4 + multiplier, 127 + multiplier, message));//数据部长度--数据校验
|
||
|
||
Isgo(message, baseNum);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表型84
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void phenotype84(string message, int baseNum)
|
||
{
|
||
int multiplier;
|
||
if (baseNum != 0)
|
||
{
|
||
//var multiplier = (whatFrame - 1) * 64;
|
||
multiplier = baseNum;
|
||
baseNum += (64 + 16);
|
||
}
|
||
else
|
||
{
|
||
multiplier = 0;
|
||
baseNum = (64 + 16);
|
||
}
|
||
|
||
shareAnalysis(message, multiplier);
|
||
|
||
StringBuilder validity = new StringBuilder("");//抄表数据有效 --无符号整型,0x26 有效,其他无效
|
||
for (int i = 44 + multiplier; i <= 45 + multiplier; i++)
|
||
{
|
||
validity.Append(message[i]);
|
||
}
|
||
if (validity.ToString() == "26")
|
||
{
|
||
Console.WriteLine("抄表数据有效");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("抄表数据无效");
|
||
}
|
||
|
||
|
||
StringBuilder signDelivery = new StringBuilder("");//瞬时流量正负值 --无符号整型,0x00 代表正,0x0a 代表负
|
||
for (int i = 46 + multiplier; i <= 47 + multiplier; i++)
|
||
{
|
||
signDelivery.Append(message[i]);
|
||
}
|
||
if (signDelivery.ToString() == "00")
|
||
{
|
||
signDelivery.Clear().Append("");
|
||
Console.WriteLine("瞬时流量为正值");
|
||
}
|
||
else
|
||
{
|
||
signDelivery.Clear().Append("-");
|
||
Console.WriteLine("瞬时流量为负值");
|
||
}
|
||
|
||
|
||
StringBuilder instantaneousFlow = new StringBuilder(""); //瞬时流量 --缩小 1000 倍为实际值,单位: m3/h
|
||
for (int i = 48 + multiplier; i <= 55 + multiplier; i++)
|
||
{
|
||
instantaneousFlow.Append(message[i]);
|
||
}
|
||
var _instantaneousFlow = float.Parse(instantaneousFlow.ToString()) / 1000;
|
||
Console.WriteLine("瞬时流量:" + signDelivery + _instantaneousFlow + "m3/h");
|
||
|
||
|
||
StringBuilder loseFlow = new StringBuilder("");//负累积流量 --缩小 10 倍为实际数值,单位: m3
|
||
for (int i = 56 + multiplier; i <= 63 + multiplier; i++)
|
||
{
|
||
loseFlow.Append(message[i]);
|
||
}
|
||
var _loseFlow = float.Parse(loseFlow.ToString()) / 10;
|
||
Console.WriteLine("负累积流量:" + signDelivery + _loseFlow + "m3");
|
||
|
||
|
||
StringBuilder loseRunTime = new StringBuilder("");//负累积运行时间 --单位: h
|
||
for (int i = 64 + multiplier; i <= 71 + multiplier; i++)
|
||
{
|
||
loseRunTime.Append(message[i]);
|
||
}
|
||
var _loseRunTime = int.Parse(loseRunTime.ToString());
|
||
Console.WriteLine("负累积运行时间:" + _loseRunTime + "h");
|
||
|
||
|
||
StringBuilder positiveFlow = new StringBuilder("");//正累积流量 --缩小 10 倍为实际数值,单位: m3
|
||
for (int i = 72 + multiplier; i <= 79 + multiplier; i++)
|
||
{
|
||
positiveFlow.Append(message[i]);
|
||
}
|
||
var _positiveFlow = float.Parse(positiveFlow.ToString()) / 10;
|
||
Console.WriteLine("正累积流量:" + _positiveFlow + "m3");
|
||
|
||
|
||
|
||
StringBuilder positiveRunTime = new StringBuilder("");//正累积运行时间 --单位: h
|
||
for (int i = 80 + multiplier; i <= 87 + multiplier; i++)
|
||
{
|
||
positiveRunTime.Append(message[i]);
|
||
}
|
||
var _positiveRunTime = int.Parse(positiveRunTime.ToString());
|
||
Console.WriteLine("正累积运行时间:" + _positiveRunTime + "h");
|
||
|
||
|
||
StringBuilder waterTemperature = new StringBuilder("");//水温 --缩小 100 倍为实际数值,单位: ℃
|
||
for (int i = 88 + multiplier; i <= 95 + multiplier; i++)
|
||
{
|
||
waterTemperature.Append(message[i]);
|
||
}
|
||
var _waterTemperature = float.Parse(waterTemperature.ToString()) / 100;
|
||
Console.WriteLine("水温:" + _waterTemperature + "℃");
|
||
|
||
|
||
StringBuilder pressure = new StringBuilder("");//压力 --缩小 1000 倍为实际数值,单位: mpa
|
||
for (int i = 96 + multiplier; i <= 103 + multiplier; i++)
|
||
{
|
||
pressure.Append(message[i]);
|
||
}
|
||
var _pressure = float.Parse(pressure.ToString()) / 1000;
|
||
Console.WriteLine("压力:" + _pressure + "mpa");
|
||
|
||
|
||
StringBuilder diagnose = new StringBuilder("");//诊断代码(仪表故障码) --当设备上报 0x06 故障时,不应再上报其他故障。
|
||
for (int i = 104 + multiplier; i <= 105 + multiplier; i++)
|
||
{
|
||
diagnose.Append(message[i]);
|
||
}
|
||
typeMalfunction(diagnose);
|
||
|
||
//数据校验 --瞬时流量符号-故障代码
|
||
Console.WriteLine("数据校验:" + binAccumulation(46 + multiplier, 105 + multiplier, message));//版本号--故障码
|
||
Console.WriteLine("校验位CS:" + binAccumulation(4 + multiplier, 107 + multiplier, message));//数据部长度--数据校验
|
||
|
||
Isgo(message, baseNum);
|
||
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 判断功能码类型
|
||
/// </summary>
|
||
/// <param name="str">功能码</param>
|
||
/// <param name="message"></param>
|
||
/// <param name="baseNum">基数【前置位设备数据总数和】</param>
|
||
public static void JudgmentFunctionCode(string str, string message, int baseNum)
|
||
{
|
||
switch ((TypeFunctionCode)int.Parse(str))
|
||
{
|
||
case TypeFunctionCode.登录帧:
|
||
LoginFrameAnalysis(message, ipEnd, socket);
|
||
break;
|
||
case TypeFunctionCode.数据帧1:
|
||
dataFramesAnalysis(message, str, baseNum);
|
||
break;
|
||
case TypeFunctionCode.校时命令:
|
||
clockAnalysis(message, ipEnd);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 报文结构类型
|
||
/// </summary>
|
||
public enum type
|
||
{
|
||
起始位,
|
||
数据部长度,
|
||
客户端地址,//12位正常,11位末加F
|
||
功能码,//00 成功,01 错误
|
||
有效负载,
|
||
校验位,
|
||
截止位
|
||
};
|
||
|
||
public enum TypeFunctionCode
|
||
{
|
||
登录帧 = 1,
|
||
数据帧1 = 8,
|
||
校时命令 = 5,
|
||
默认 = 99
|
||
}
|
||
|
||
/// <summary>
|
||
/// 工作模式为枚举型,取值范围 0x00 定时开机,0x01 实时在线
|
||
/// </summary>
|
||
public enum TypeworkPattern
|
||
{
|
||
定时开机 = 0,
|
||
实时在线
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断表型
|
||
/// </summary>
|
||
/// <param name="phenotype"></param>
|
||
public static string typePheno(StringBuilder phenotype)
|
||
{
|
||
StringBuilder s = new StringBuilder("");
|
||
switch (phenotype.ToString())
|
||
{
|
||
//--0x81 SCL-61D5/6 单向不锈钢带温度流量计 SCL61D6 单向不锈钢带温度流量计
|
||
//--0x83 SCL-61D5/6 双向不锈钢带温度流量计 SCL61D6 双向不锈钢带温度流量计
|
||
//--0x84 SCL-61D5/6 不锈钢带压力 SCL61D6 不锈钢带压力
|
||
case "81":
|
||
s.Append("SCL61D6 单向不锈钢带温度流量计");
|
||
Console.WriteLine("表型:" + s);
|
||
s.Clear().Append("81");
|
||
break;
|
||
case "83":
|
||
s.Append("SCL61D6 双向不锈钢带温度流量计");
|
||
Console.WriteLine("表型:" + s);
|
||
s.Clear().Append("83");
|
||
break;
|
||
case "84":
|
||
s.Append("SCL61D6 不锈钢带压力");
|
||
Console.WriteLine("表型:" + s);
|
||
s.Clear().Append("84");
|
||
break;
|
||
}
|
||
return s.ToString().Trim();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断报警码**只在使用08 码上报数据时才会存在
|
||
/// </summary>
|
||
/// <param name="alarmCode"></param>
|
||
public static void typeAlarmcode(StringBuilder alarmCode)
|
||
{
|
||
switch (alarmCode.ToString())
|
||
{
|
||
case "01":
|
||
alarmCode.Clear().Append("正向流量超上限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "02":
|
||
alarmCode.Clear().Append("正向流量超下限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "04":
|
||
alarmCode.Clear().Append("负向流量超上限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "08":
|
||
alarmCode.Clear().Append("负向流量超下限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "10":
|
||
alarmCode.Clear().Append("压力超上限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "20":
|
||
alarmCode.Clear().Append("压力超下限");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "40":
|
||
alarmCode.Clear().Append("预留");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
case "80":
|
||
alarmCode.Clear().Append("预留");
|
||
Console.WriteLine("报警码:" + alarmCode);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断故障码**当设备上报 0x06 故障时,不应再上报其他故障。
|
||
/// </summary>
|
||
/// <param name="diagnose"></param>
|
||
public static void typeMalfunction(StringBuilder diagnose)
|
||
{
|
||
switch (diagnose.ToString())
|
||
{
|
||
case "01":
|
||
diagnose.Clear().Append("池电压低于3.37V,需要更换电池");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "02":
|
||
diagnose.Clear().Append("空管或者换能器故障无测量信号");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "03":
|
||
diagnose.Clear().Append("代码01 和代码02 同时发生");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "04":
|
||
diagnose.Clear().Append("电池电压低于3.3V,必须更换电池");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "05":
|
||
diagnose.Clear().Append("传感器和换能器之间通讯故障,无通讯");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "06":
|
||
diagnose.Clear().Append("E2PROM 损坏");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "10":
|
||
diagnose.Clear().Append("供水温度传感器故障(短路、开路)或供水温度低于2℃");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "20":
|
||
diagnose.Clear().Append("供水温度超出150℃");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "40":
|
||
diagnose.Clear().Append("回水温度传感器故障(短路、开路)或回水温度低于2℃");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
case "80":
|
||
diagnose.Clear().Append("回水温度超出150℃");
|
||
Console.WriteLine("故障码:" + diagnose);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
}
|
||
}
|