1. TCP Server 线程监听
2. 串口数据监听
3. 定时器 1分钟1次 历史记录保存
4. 参数超过上限或下限值后,触发执行操作
5. 实时日志查看
6. 支持 参数配置 和 操作配置 ( 可远程配置后一键下载 )
软件界面:
软件代码:
Public Class Form1
Dim Address() As System.Net.IPAddress '定义一个IP地址集合
Dim MyPcName As String
Dim MaxIpCount As Integer
'服务端的Socket
Dim listener As Socket
'与客户端会话的Socket
Dim mySocket As Socket
'服务端的运行状态
Dim IsRun As Boolean = False
'监听接收数据线程
Dim myThread As Thread
Dim myPath As String
Dim CONFIG(100) As String
Dim CONFIG_L As Integer
Dim CONTROL(100) As String
Dim CONTROL_L As Integer
Dim names(100) As String
Dim values(100) As String
Dim labels(100) As Label
Dim objTimer As Timer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'初始化串口
initCom()
'初始化波特率
initBps()
'获取TCP域名
MyPcName = System.Net.Dns.GetHostName()
'获取本机IP对内,对外地址,使用GetHostEntry方法
Address = System.Net.Dns.GetHostEntry(MyPcName).AddressList
MaxIpCount = UBound(Address)
HOST.Text = GetInsideIP()
'PORT
PORT.Text = "11999"
'path
myPath = System.Environment.CurrentDirectory
'myPath = "C:\Users\86182\Desktop\wlw"
echo("加载:数据参数")
Dim i As Integer = 0
Dim line As String
Dim sr As StreamReader = New StreamReader(myPath + "\config.txt", System.Text.Encoding.Default)
Do While sr.Peek() > 0
line = sr.ReadLine()
echo(line)
CONFIG(i) = line
'split
Dim arr() As String = Split(line, ",")
CANSHU.Items.Add(arr(1))
addOne(arr(1), "--", i)
i = i + 1
Loop
CONFIG_L = i
sr.Close()
sr = Nothing
echo("加载:控制参数")
i = 0
Dim line2 As String
Dim sr2 As StreamReader = New StreamReader(myPath + "\control.txt", System.Text.Encoding.Default)
Do While sr2.Peek() > 0
line2 = sr2.ReadLine()
echo(line2)
CONTROL(i) = line2
i = i + 1
'split
Dim arr() As String = Split(line2, ",")
CMD.Items.Add(arr(0))
Loop
CONTROL_L = i
sr2.Close()
sr2 = Nothing
'初始化定时器
Dim tcb As New TimerCallback(AddressOf Me.TimerMethod)
objTimer = New Timer(tcb, Nothing, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(60))
End Sub
'串口接收触发
Private Sub TimerCB(ByVal sender As Object, ByVal e As EventArgs)
Dim datetime As String
Dim filepath As String
Dim ii As Integer
Dim row() As String
Dim title As String
Dim str As String = HISBTN.Text
echo(str)
If (str = "取消保存(1分钟1次)") Then
title = "采集时间,"
datetime = Format(Now, "yyyy_MM_dd")
filepath = myPath & "\data\" & datetime & ".csv"
echo(" 保存历史数据文件-> " & filepath)
If Dir(filepath) = "" Then
For ii = 0 To (CONFIG_L - 1)
If (CONFIG(ii) <> "") Then
row = Split(CONFIG(ii), ",")
title = title & row(1) & ","
End If
Next ii
' 创建文件
Dim NewText As FileStream = File.Create(filepath)
Dim info As Byte() = New UTF8Encoding(True).GetBytes(title)
NewText.Write(info, 0, info.Length)
NewText.Close()
echo(" 创建历史文件-> ok")
Else
'获取时间点
Dim dt2 As String
dt2 = Format(Now, "yyyy-MM-dd hh:mm:ss")
'获取数据值
Dim val2 As String
val2 = dt2 & ","
For ii = 0 To (CONFIG_L - 1)
If (CONFIG(ii) <> "") Then
If values(ii) = "--" Then
values(ii) = ""
End If
val2 = val2 & values(ii) & ","
End If
Next ii
'向文件写入数据
Dim NewText As FileStream = File.Open(filepath, FileMode.Append)
Dim info As Byte() = New UTF8Encoding(True).GetBytes(vbNewLine + val2)
NewText.Write(info, 0, info.Length)
NewText.Close()
echo(" 保存历史数据完成-> " & val2)
End If
End If
End Sub
'1分钟执行1次 保存历史数据
Public Sub TimerMethod(ByVal state As Object)
Me.Invoke(New EventHandler(AddressOf TimerCB)) '调用接收数据函数
End Sub
Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
'关闭串口
closeCom()
'关闭TCP
tcpClose()
'关定时器
objTimer.Dispose()
End Sub
'初始化串口
Public Sub initCom()
COM.Items.Clear()
Dim portList() As String = System.IO.Ports.SerialPort.GetPortNames()
Console.WriteLine("The following serial ports were found:")
' Display each port name to the console.
Dim port As String
For Each port In portList
Console.WriteLine(port)
COM.Items.Add(port)
Next port
End Sub
'初始化波特率
Public Sub initBps()
BTV.Items.Add("115200")
BTV.Items.Add("9600")
BTV.Items.Add("4800")
End Sub
Private Sub LOGBTN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LOGBTN.Click
Dim str As String = LOGBTN.Text
If str = "显示日志" Then
LOGBTN.Text = "隐藏日志"
LOG.Visible = True
Else
LOGBTN.Text = "显示日志"
LOG.Visible = False
End If
End Sub
'连接串口
Private Sub COMBTN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles COMBTN.Click
Dim str As String = COMBTN.Text
If str = "连接" Then
openCom()
Else
closeCom()
End If
End Sub
'提示信息
Public Sub alert(ByVal msg As String)
MsgBox(msg, vbYes, "")
End Sub
'显示日志信息
Public Sub echo(ByVal msg As String)
LOG.Text = LOG.Text & Format(Now, "hh:mm:ss") & " -> " & msg & vbNewLine
LOG.SelectionStart = LOG.Text.Length
LOG.ScrollToCaret()
End Sub
'打开串口
Public Sub openCom()
Dim comstr As String = COM.Text
Dim btvstr As String = BTV.Text
If comstr <> "" Then
If btvstr <> "" Then
SerialPort1.BaudRate = Val(btvstr) '波特率
SerialPort1.PortName = comstr '串口名称
SerialPort1.DataBits = 8 '数据位
SerialPort1.StopBits = IO.Ports.StopBits.One '停止位
SerialPort1.Parity = IO.Ports.Parity.None '校验位
Try
SerialPort1.Open() '打开串口
If SerialPort1.IsOpen = True Then
COMBTN.Text = "断开"
End If
Catch ex As Exception
alert("错误,串口被占用")
End Try
Else
alert("请选择波特率")
End If
Else
alert("请选择串口")
End If
End Sub
'关闭串口
Public Sub closeCom()
Try
SerialPort1.Close() '关闭
If SerialPort1.IsOpen = False Then
COMBTN.Text = "连接"
End If
Catch ex As Exception
alert(ex.Message)
End Try
End Sub
'串口数据接收
Public Sub Sp_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Me.Invoke(New EventHandler(AddressOf Sp_Receiving)) '调用接收数据函数
End Sub
'串口接收触发
Private Sub Sp_Receiving(ByVal sender As Object, ByVal e As EventArgs)
Dim strIncoming As String
Try
If SerialPort1.BytesToRead > 0 Then
Threading.Thread.Sleep(100) '添加的延时
strIncoming = SerialPort1.ReadExisting.ToString '读取缓冲区中的数据
SerialPort1.DiscardInBuffer()
Dim hexstr As String = StrToHex(strIncoming)
echo("串口接收:" & hexstr)
showData(hexstr)
End If
Catch ex As Exception
echo("串口接收错误:" & ex.Message)
End Try
End Sub
'将字符串转换为16进制
Public Function StrToHex(ByRef Data As String) As String
Dim byteArray() As Byte
Dim hexNumbers As System.Text.StringBuilder = New System.Text.StringBuilder
byteArray = System.Text.ASCIIEncoding.ASCII.GetBytes(Data)
For i As Integer = 0 To byteArray.Length - 1
Dim st As String = byteArray(i).ToString("x")
Dim s2 As String = st.PadLeft(2, "0")
hexNumbers.Append(s2)
Next
Return hexNumbers.ToString()
End Function
'串口发送命令
Public Sub sendHex(ByVal str As String)
Try
Dim bytes(1) As Byte
Dim i As Integer
For i = 0 To (str.Length / 2 - 1)
bytes(0) = Convert.ToByte(str.Substring(i * 2, 2), 16)
SerialPort1.Write(bytes, 0, 1)
Next
echo("串口发送:" & str)
Catch ex As Exception
echo("串口发送错误:" & ex.Message)
End Try
End Sub
Private Sub CMDBTN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CMDBTN.Click
Dim str As String = CMDBTN.Text
If str = "开启" Then
Dim cs As String = CANSHU.Text
Dim max As String = UP.Text
Dim min As String = DOWN.Text
Dim ops As String = CMD.Text
If (cs <> "") Then
If (ops <> "") Then
If max <> "" Or min <> "" Then
CMDBTN.Text = "关闭"
Else
alert("请输入上限值或下限值")
End If
Else
alert("请选择操作")
End If
Else
alert("请选择参数")
End If
Else
CMDBTN.Text = "开启"
End If
End Sub
'获取本机IP
Public Function GetInsideIP() As String
Dim ReturnIP As String = "127.0.0.1" '无网络则返回此IP
Dim InsideIP As String = "192.168.*.*" 'C类网局域网IP
Dim InsideIP2 As String = "10.0.*.*" 'A类网局域网IP
If MaxIpCount > 0 Then
Dim Ipstr As String
Dim i As Integer
For i = 0 To MaxIpCount
Ipstr = Address(i).ToString
If Ipstr Like InsideIP Or Ipstr Like InsideIP2 Then
ReturnIP = Ipstr
End If
Next
End If
Return ReturnIP
End Function
'TCP链接
Private Sub TCPBTN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TCPBTN.Click
Dim str As String = TCPBTN.Text
If str = "连接" Then
myThread = New Thread(AddressOf tcpOpen)
myThread.Start()
TCPBTN.Text = "断开"
Else
tcpClose()
TCPBTN.Text = "连接"
End If
End Sub
'打开TCP
Public Sub tcpOpen()
Dim myport As String = PORT.Text
Dim bytes() As Byte = New [Byte](1024) {}
Dim localEndPoint As New IPEndPoint(Net.IPAddress.Parse("127.0.0.1"), Val(myport))
'初始化socket
listener = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
'绑定端口
listener.Bind(localEndPoint)
'开始监听
listener.Listen(10)
Try
mySocket = listener.Accept()
IsRun = True
While True
Dim bytesRec As Integer = mySocket.Receive(bytes)
Dim mData As String = Encoding.UTF8.GetString(bytes, 0, bytesRec)
BeginInvoke(New EventHandler(AddressOf tcpReceive), mData) 'Invoke保证线程安全
End While
Catch ex As Exception
IsRun = False
End Try
End Sub
'TCP收到信息
Sub tcpReceive(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim hexstr As String = StrToHex(sender.ToString)
echo("TCP接收:" & hexstr)
showData(hexstr)
End Sub
'关闭TCP
Public Sub tcpClose()
Try
IsRun = False
listener.Close()
mySocket = Nothing
myThread.Abort()
Catch ex As Exception
End Try
End Sub
'数据分析
Public Sub showData(ByVal hexstr As String)
echo("解析:数据参数 " & CONFIG_L)
Dim oneArr() As String
Dim ii As Integer = 0
For ii = 0 To (CONFIG_L - 1)
Dim one As String = CONFIG(ii)
echo("--------" & ii & "----------")
echo(one)
If one.Length > 1 Then
oneArr = Split(one, ",")
Dim unit1 As String
Dim suo1 As String
Dim jie1 As String
Dim name1 As String
name1 = oneArr(1)
unit1 = oneArr(3)
suo1 = oneArr(2)
jie1 = oneArr(5)
echo(" 1.解析:" + name1 + " " + suo1 + " " + unit1 + " " + jie1)
If hexstr.Length > 6 Then
If jie1.Length > 6 Then
echo(" 2.符合条件,收到数据 >6, 解析规则 >6")
Dim HData6 As String
Dim jie6 As String
HData6 = hexstr.Substring(0, 6)
jie6 = jie1.Substring(0, 6)
echo(" 3.数据解析 6:" + HData6 + "= 6:" + jie6)
' 验证通过
If HData6 = jie6 Then
Dim s As Integer
Dim e As Integer
Dim sData As String
s = jie1.IndexOf("X")
e = jie1.LastIndexOf("X")
echo(" 4.可以解析,位置:" & s & "-" & e)
If hexstr.Length > e Then
sData = Mid(hexstr, s, (e - s) + 1)
echo(" 5.截取值:" & sData)
Dim myval As Long
myval = Val("&H" & sData)
Dim myxs As Double
myxs = myval * Val(suo1)
echo(" 6.数字:" & myval & " 数值:" & myxs & " 名称:" & name1)
labels(ii).Text = name1 & vbNewLine & "" & myxs & " " & unit1
values(ii) = myxs
'开启继电器监测
Dim str As String = CMDBTN.Text
If (str = "关闭") Then
Dim cs As String = CANSHU.Text
echo(" 7.比较参数:" & cs & " = " & name1)
If (cs = name1) Then
Dim max As String = UP.Text
Dim min As String = DOWN.Text
If myxs > Val(max) Or myxs < Val(min) Then
'执行继电器操作
Dim cmd As String = getOpcmd()
If (cmd <> "") Then
echo("8.执行继电器命令:" + cmd)
sendHex(cmd)
End If
End If
End If
End If
End If
End If
End If
End If
End If
Next
End Sub
Public Function getOpcmd() As String
Dim opname As String = CMD.Text
Dim oneArr() As String
Dim ii As Integer = 0
For ii = 0 To (CONTROL_L - 1)
Dim one As String = CONTROL(ii)
If one.Length > 1 Then
oneArr = Split(one, ",")
If (oneArr(0) = opname) Then
Return oneArr(1)
End If
End If
Next
Return ""
End Function
'保存数据
Private Sub HISBTN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HISBTN.Click
Dim str As String = HISBTN.Text
If (str = "保存记录(1分钟1次)") Then
Try
If Dir(myPath & "\data\", vbDirectory) = "" Then
'创建文件夹
MkDir(myPath & "\data\")
End If
Catch ex As Exception
End Try
HISBTN.Text = "取消保存(1分钟1次)"
Else
objTimer.Dispose()
HISBTN.Text = "保存记录(1分钟1次)"
End If
End Sub
'添加一个参数
Private Sub addOne(ByVal name As String, ByVal num As String, ByVal i As Integer)
Dim c As Integer
Dim r As Integer
r = i / 10
c = i Mod 6
If c < 0 Then
c = 0
End If
Dim myl As New Label
myl.Text = name + vbNewLine + num
myl.TextAlign = ContentAlignment.MiddleCenter
myl.Font = New Font("Microsoft Yahei", 12, FontStyle.Bold, GraphicsUnit.Point)
myl.Width = 155
myl.Height = 90
myl.Location = New Point((c * 181) + 20, (r * 115) + 90)
myl.BackColor = Color.LightGray
Controls.Add(myl)
labels(i) = myl
names(i) = name
values(i) = num
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
LOG.Text = ""
End Sub
End Class
感谢您的支持,写的文章如对您有所帮助,开源不易,请您打赏,谢谢啦~