C#对于处理window操作系统下的设备有天然的优势,对于大多数设备读写等操作来说基本上够了,这里只讨论通过普通的大多数的设备的操作。涉及到两大类SerialPort类,Socket的一些操作。不一定好,但希望分享出去,让更多的人受益。。
由于设备的读写方式不同,串口,网口,usb,等各种各样不同的方式,所以对外的操作,可能就达不到统一,没法集中处理,造成很大程度代码冗余,会给维护带来很大不便。需要一个父类来对不同操作进行统一的一个约束,同时可以对外有一个统一的j接口,方便业务上边的一些处理。
代码语言:javascript复制 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace EquipmentOption
7 {
8 public abstract class Equipment
9 {
10
11 /// <summary>
12 /// 读取到的Code
13 /// </summary>
14 public string Code;
15 /// <summary>
16 /// 错误消息
17 /// </summary>
18 public string Error = string.Empty;
19 public BaseEquipment EquipmentModel;
20
21 public int ReadTimeOut=500;
22 public Equipment(BaseEquipment Model)
23 {
24 this.EquipmentModel = Model;
25 }
26 /// <summary>
27 /// 扫描事件
28 /// </summary>
29 private int scanning;
30 public int Scanning
31 {
32 get
33 {
34 return this.scanning;
35 }
36 set
37 {
38 this.scanning = value;
39 EquipmentArgs e = new EquipmentArgs(this.Code, this.Error);
40 OnSetVelues(e);
41 }
42 }
43 public event SetEventHandler SetEvent;
44 public delegate void SetEventHandler(object sender, EquipmentArgs e);
45 public class EquipmentArgs : EventArgs
46 {
47 public string Code;
48 public string Error;
49 public EquipmentArgs(string SnCode,string error)
50 {
51 this.Code = SnCode;
52 this.Error = error;
53 }
54 }
55 public void OnSetVelues(EquipmentArgs e)
56 {
57 if (this.SetEvent != null)
58 {
59 this.SetEvent(this, e);
60 }
61 }
62 /// <summary>
63 /// 检测设备
64 /// </summary>
65 /// <param name="message">错误消息返回值,仅当返回false才有值</param>
66 /// <returns></returns>
67 public abstract bool test(out string message);
68 /// <summary>
69 /// 给设备发送指令
70 /// </summary>
71 /// <param name="command">指令内容</param>
72 /// <param name="type">指令类型</param>
73 /// <returns></returns>
74 public abstract string SendMessage(String command, CommandType type);
75 }
76
77 }
父类里边主要定义了一些公用的属性,以及一个简单的事件转发。这个事件转发用于统一网口设备和串口设备的获取数据方式
调用方式如下:
代码语言:javascript复制 private void Form1_Load(object sender, EventArgs e)
{
Equipment Comquip = new ComEquipment(new BaseEquipment());
Comquip.SetEvent = Equipment_GetCodeEvent;
Equipment IPEquip = new IPEquipment(new BaseEquipment());
IPEquip.SetEvent = Equipment_GetCodeEvent;
}
void Equipment_GetCodeEvent(object sender, Equipment.EquipmentArgs e)
{
string code = e.Code;//这里的Code就是从设备中读取到的值
}
可以把需要用到的基础消息丢到baseEquipment中用来初始化对应的设备,然后,把对于设备读取到的信息就是这里的e.code。不管网口串口都是一样的返回.
设备的操作无非读写
对于用串口连接的设备:
代码语言:javascript复制 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO.Ports;
6 using System.Threading;
7 namespace EquipmentOption
8 {
9 public class ComEquipment : Equipment
10 {
11 private SerialPort Port;
12 public ComEquipment(BaseEquipment baseModel) :
13 base(baseModel)
14 {
15 this.Port = new SerialPort(baseModel.Port);
16 Port.BaudRate = baseModel.BaudRate;
17 Port.StopBits = (StopBits)baseModel.StopBit;
18 Port.Parity = (Parity)baseModel.ParityCheck;
19 this.Port.DataReceived = Port_DataReceived;
20 }
21 //事件转发
22 void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
23 {
24 Thread.Sleep(this.EquipmentModel.SleepTime);
25 this.Error = string.Empty;
26 this.Code = string.Empty;
27 try
28 {
29 switch (this.EquipmentModel.ReadType)
30 {
31 case 1:
32 this.Code = (sender as SerialPort).ReadLine();
33 break;
34 case 2:
35 this.Code = (sender as SerialPort).ReadExisting();
36 break;
37 default:
38 Error = string.Concat(this.EquipmentModel.EquipmentName, "读取有误");
39 break;
40 }
41 this.Scanning;//这里切记是属性值变化才会触发事件
42
43 }
44 catch
45 {
46 Error = string.Concat(this.EquipmentModel.EquipmentName, "配置错误,请调整");
47 }
48 }
49
50 /// <summary>
51 /// 检测
52 /// </summary>
53 /// <param name="message"></param>
54 /// <returns></returns>
55 public override bool test(out string message)
56 {
57 message = "";
58 bool result = false;
59 if (this.Port != null)
60 {
61 try
62 {
63 Port.Open();
64 result = true;
65 }
66 catch
67 {
68 message = string.Concat("设备", this.EquipmentModel.EquipmentName, "异常");
69 result = false;
70 }
71 finally
72 {
73 if (Port.IsOpen)
74 {
75 Port.Close();
76 }
77 }
78 }
79 else
80 {
81 message = string.Concat("设备", this.EquipmentModel.EquipmentName, "初始化失败");
82 result = false;
83 }
84 return result;
85 }
86 /// <summary>
87 /// 发送命令
88 /// </summary>
89 /// <param name="command">命令</param>
90 public override string SendMessage(String command, CommandType type)
91 {
92 if (!String.IsNullOrEmpty(command) && this.Port.IsOpen)
93 {
94 switch (type)
95 {
96 case CommandType.GetBytes:
97 Byte[] commandsGetBytes = CommandConvert.CommandByGetBytes(command);
98 this.Port.Write(commandsGetBytes, 0, commandsGetBytes.Length);
99 break;
100 case CommandType.Command16:
101 Byte[] commands16 = CommandConvert.CommandFrom16(command);
102 this.Port.Write(commands16, 0, commands16.Length);
103 break;
104 case CommandType.Command10:
105 Byte[] commands10 = CommandConvert.CommandFrom10(command);
106 this.Port.Write(commands10, 0, commands10.Length);
107 break;
108 case CommandType.CommandText:
109 this.Port.Write(command);
110 break;
111 }
112 return this.Port.PortName "发送数据:" command;
113 }
114 else
115 {
116 return "串口" this.Port.PortName "未打开";
117 }
118 }
119 }
120 }
对于用网口连接的设备:
代码语言:javascript复制 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Net;
6 using System.Net.Sockets;
7 using System.Threading;
8
9 namespace EquipmentOption
10 {
11 public class IPEquipment : Equipment
12 {
13 private IPEndPoint IPPort;
14 private IPAddress IP;
15 public IPEquipment(BaseEquipment baseModel) :
16 base(baseModel)
17 {
18 int Port = 0;
19 if (int.TryParse(baseModel.Port, out Port))
20 {
21 this.IP = IPAddress.Parse(baseModel.IPAddress);
22 this.IPPort = new IPEndPoint(IP, Port);
23 Thread t = new Thread(new ParameterizedThreadStart(ScanEvent));
24 t.Start(IPPort);
25 }
26 }
27
28 public override bool test(out string message)
29 {
30 bool result = false; message = "";
31 Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建Socket
32 try
33 {
34 c.SendTimeout = 5000;
35 c.Connect(IPPort); //连接到服务器
36 result = true;
37 }
38 catch
39 {
40 message =string.Concat("设备" , this.EquipmentModel.EquipmentName , "异常");
41 result = false;
42 }
43 finally
44 {
45 c.Close();
46 }
47 return result;
48 }
49 public void ScanEvent(object ipe)
50 {
51 while (true)
52 {
53 try
54 {
55 //创建Socket并连接到服务器
56 Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建Socket
57 c.Connect((IPEndPoint)ipe); //连接到服务器
58 //接受从服务器返回的信息
59 byte[] recvBytes = new byte[1024];
60 int bytes;
61 //bytes = c.Receive(recvBytes, recvBytes.Length, 0); //从服务器端接受返回信息
62 bytes = c.Receive(recvBytes);
63 string Code = Encoding.Default.GetString(recvBytes, 0, bytes);
64 Code = Code.Replace(EquipmentModel.Suffix, "");
65 this.Code = Code;
66 c.Close();
67 this.Scanning;
68 }
69 catch(Exception ex)
70 {
71 Error = ex.ToString();
72 continue;
73 }
74 }
75 }
76
77 public override string SendMessage(string command, CommandType type)
78 {
79 //new mothed to SendMessage;
80 return "";
81 }
82 }
83 }
对于扩展而言,需要做的仅仅是不同类别的设备再增加不同的子类去继承抽象类.