开发平台:VS2012及以上版本,.Net 4.0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
namespace TestModel
{
public partial class Form1 : Form
{
/// <summary>
/// 服务
/// </summary>
AsySocket.Server sever = null;
/// <summary>
/// 服务端口
/// </summary>
int Port;
/// <summary>
/// 服务类型
/// </summary>
AsySocket.Service_Type severType;
/// <summary>
/// 消息缓存
/// </summary>
AsySocket.MemQueue<string> msgQueue = new AsySocket.MemQueue<string>();
public Form1()
{
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
}
private void btn_StartSever_Click(object sender, EventArgs e)
{
if (!int.TryParse(tbox_SeverPort.Text.Trim(), out Port))
{
Port = 10001;
tbox_SeverPort.Text = Port.ToString();
}
if (rbtn_SeverType.Checked)
{
severType = AsySocket.Service_Type.TCP;
}else{
severType = AsySocket.Service_Type.UDP;
}
sever = new AsySocket.Server();
sever.onClose += new AsySocket.onClose(sever_onClose);
sever.OnRegist += new AsySocket.onRegist(sever_OnRegist);
sever.onCmdRecv += new AsySocket.onCmdRecv(sever_onCmdRecv);
sever.onError += new AsySocket.onError(sever_onError);
sever.Start(severType, Port);
btn_StartSever.Enabled = false;
btn_StopSever.Enabled = true;
}
#region 事件处理
private void sever_onClose(AsySocket.CmdTag cmd)
{
msgQueue.Add("设备" + cmd.DeviceID + "断开。");
lbox_deviceList.Items.Remove(cmd.DeviceID.ToString());
}
private void sever_OnRegist(AsySocket.CmdTag cmd)
{
msgQueue.Add("收到设备" + cmd.DeviceID + "注册登录信息。");
sever.SetOnLine(cmd.DeviceID, 1); //响应设备注册;1允许,0不允许
lbox_deviceList.Items.Add(cmd.DeviceID.ToString());
}
private void sever_onCmdRecv(AsySocket.CmdTag cmd)
{
Exectue(cmd);
}
private void sever_onError(string msg)
{
msgQueue.Add(msg);
}
#endregion
private void btn_StopSever_Click(object sender, EventArgs e)
{
if (sever == null)
{
return;
}
try
{
sever.Stop();
sever = null;
btn_StartSever.Enabled = true;
btn_StopSever.Enabled = false;
}
catch { }
}
/// <summary>
/// 解析收到的数据
/// </summary>
/// <param name="cmd"></param>
private void Exectue(AsySocket.CmdTag cmd)
{
try
{
switch (cmd.CmdType)
{
case 0xE0:
{
Exectue_0xE0(cmd);
break;
}
case 0xF0:
{
Exectue_0xF0(cmd);
break;
}
default:
{
msgQueue.Add(string.Format("收到设备{0}数据——{1}。", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param)));
break;
}
}
}
catch (Exception ex){
msgQueue.Add(string.Format("解析数据错误{0},{1}\r\n{2}", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param), ex.Message));
}
}
private void Exectue_0xE0(AsySocket.CmdTag cmd)
{
switch (cmd.CmdCode)
{
case 0xD0: //设备回复抄表指令
{
if (cmd.CmdState != AsySocket.CommandState.CMD_STATE_OK)
{
msgQueue.Add(cmd.DeviceID + " 执行抄表指令失败");
}
msgQueue.Add(cmd.DeviceID + " 执行抄表指令成功");
break;
}
case 0xB2: //设请求端口配置数据
{
if (cmd.Param.Length < 9) {
msgQueue.Add(string.Format("{0}请求端口配置数据错误——{1}。", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param)));
break;
}
// string edition;
byte port = cmd.Param[7];
byte index = cmd.Param[8];
cmd.CmdCode = 0xB1; //发送配置信息
int meterCount = 1; //表数量,此处举例只有一个表地址;根据实际表数量修改
cmd.Param = new byte[meterCount * 8];
long meterAddr = 0;
if (tbox_cmdParam.Text.Trim().Length == 0)
{
break;
}
long.TryParse(tbox_cmdParam.Text.Trim(), out meterAddr);
Utils.UINT64ToByteArray_LitMode(cmd.Param, (ulong)Utils.ToBCD(meterAddr), 0);
sever.Send(cmd); //发送配置关系 响应设备请求。
break;
}
case 0xB3:
{
msgQueue.Add(cmd.DeviceID + " 请求配置水表与端口关系完成");
break;
}
case 0xD1: //汇报水表读数
{
if (cmd.Param.Length < 13)
{
msgQueue.Add(string.Format("{0}汇报水表读数错误——{1}。", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param)));
break;
}
int i = 0;
while (i < cmd.Param.Length)
{
try
{
ulong meterNo = Utils.FromBCD(Utils.ByteArrayToUINT64_LitMode(cmd.Param, i));
if (meterNo == 0)
{
i += 13;
continue;
}
byte status = cmd.Param[i + 12];
if (status == 0xff) //读表失败
{
i += 13;
continue;
}
uint meterReadNum = Utils.ByteArrayToUINT32_LitMode(cmd.Param, i + 8) / 100; //设备上传的是乘以了100后的数据,所以在此除以100
msgQueue.Add(string.Format("收到设备{0}读水表数——表地址{1},读数{2},状态{3}。", cmd.DeviceID, meterNo, meterReadNum, status));
}
catch { }
i += 13;
}
break;
}
default:
{
msgQueue.Add(string.Format("收到设备{0}数据——{1}。", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param)));
break;
}
}
}
private void Exectue_0xF0(AsySocket.CmdTag cmd)
{
switch (cmd.CmdCode)
{
case 0xAA:
{
if (cmd.Param.Length < 2) break;
int code = cmd.Param[1];
code = (code << 8) | cmd.Param[0];
switch (code)
{
case 0x05:
{
int index = cmd.Param[2];
int port = cmd.Param[4];
port = (port << 8) | cmd.Param[3];
string type = "TCP";
if (cmd.Param[5] == 0x01)
{
type = "UDP";
}
string stucte = "停用";
if (cmd.Param[6] == 0x01)
{
stucte = "启用";
}
string IP = ASCIIEncoding.Default.GetString(cmd.Param, 7, cmd.Param.Length - 7);
msgQueue.Add(string.Format("{0}设备服务器信息:序号:{1} IP:{2} 端口:{3} 类型:{4} 状态:{5}", cmd.DeviceID,
index, IP, port, type, stucte));
break;
}
}
break;
}
default:
{
msgQueue.Add(string.Format("收到设备{0}数据——{1}。", cmd.DeviceID, AsySocket.FormatHelper.ByteArrayToHexString(cmd.Param)));
break;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btn_SendCmd_Click(object sender, EventArgs e)
{
long deviceNo = getDeviceID();
if (deviceNo == 0)
{
MessageBox.Show("请选择在线设备。");
return;
}
string codestr = cbox_CmdCode.SelectedItem.ToString();
if (string.IsNullOrEmpty(codestr))
{
MessageBox.Show("请选择指令类型。");
return;
}
if (sever == null)
{
MessageBox.Show("请先启动服务。");
return;
}
AsySocket.CmdTag cmd = new AsySocket.CmdTag();
cmd.DeviceID = deviceNo;
cmd.CmdState = AsySocket.CommandState.CMD_STATE_SEND;
if (!getCmdCode(codestr, ref cmd)) return;
sever.Send(cmd);
}
private long getDeviceID()
{
long deviceNo = 0;
if (lbox_deviceList.Items.Count == 0)
{
return deviceNo;
}
long.TryParse(lbox_deviceList.Text, out deviceNo);
return deviceNo;
}
/// <summary>
/// 组织命令
/// </summary>
/// <param name="type"></param>
/// <param name="cmd"></param>
/// <returns></returns>
private bool getCmdCode(string type,ref AsySocket.CmdTag cmd)
{
switch (type)
{
case "全部抄表":
{
cmd.CmdCode = 0xD0;
cmd.CmdType = 0xE0;
return true;
}
case "单表抄表":
{
cmd.CmdCode = 0xCF;
cmd.CmdType = 0xE0;
cmd.Param = new byte[8];
long meterAddr = 0;
if (tbox_cmdParam.Text.Trim().Length == 0) {
msgQueue.Add("请填写水表地址");
return false;
}
long.TryParse(tbox_cmdParam.Text.Trim(), out meterAddr);
Utils.UINT64ToByteArray_LitMode(cmd.Param, (ulong)Utils.ToBCD(meterAddr), 0);
return true;
}
case "配置表地址":
{
cmd.CmdCode = 0xB0;
cmd.CmdType = 0xE0;
byte port = 0;
if (tbox_cmdParam.Text.Trim().Length == 0 || cbox_port.Text.Length==0)
{
msgQueue.Add("必须填写水表地址和选择端口。");
return false;
}
byte.TryParse(cbox_port.Text.Trim(), out port);
cmd.Param = new byte[9];
cmd.Param[0] = port;
cmd.Param[1] = 1; //表数量 根据实际接入数量赋值;
Utils.DateTimeToByteArray_LitMode(DateTime.Now, ref cmd.Param, 2); //赋值当前时间
return true;
}
case "查询服务器配置":
{
cmd.CmdCode = 0xAA;
cmd.CmdType = 0xF0;
cmd.Param = new byte[2];
cmd.Param[0] = 0x05;
cmd.Param[1] = 0x00;
return true;
}
}
return false;
}
private void timer1_Tick(object sender, EventArgs e)
{
while (msgQueue.Count > 0)
{
if (tbox_Msg.TextLength > 32768)
{
tbox_Msg.Clear();
}
tbox_Msg.AppendText(string.Format("{0}:{1}\r\n", DateTime.Now.ToLongTimeString(), msgQueue.Get()));
}
}
private void Form1_Closing(object sender, FormClosingEventArgs e)
{
timer1.Enabled = false;
try
{
sever.Stop();
}
catch { }
}
private void btn_ClearMsg_Click(object sender, EventArgs e)
{
tbox_Msg.Clear();
}
}
}