381 lines
14 KiB
VB.net
381 lines
14 KiB
VB.net
|
|
Imports System.Net
|
|||
|
|
Imports System.Net.Sockets
|
|||
|
|
Imports System.Threading
|
|||
|
|
|
|||
|
|
Public Class DevNetworkCommunication
|
|||
|
|
Inherits Transmitter
|
|||
|
|
|
|||
|
|
Public m_Serial As Socket
|
|||
|
|
|
|||
|
|
Public m_SerialComfig As UDPComfig
|
|||
|
|
Public m_Control As Control
|
|||
|
|
|
|||
|
|
'接收数据队列
|
|||
|
|
Public m_ReceiveQueue As List(Of Cmdconfig) = New List(Of Cmdconfig)
|
|||
|
|
'特殊接收处理标志
|
|||
|
|
Public m_SpecialReceiveFlag As Integer
|
|||
|
|
Public recvBufferli As List(Of Byte)
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 透传数据包头
|
|||
|
|
''' </summary>
|
|||
|
|
Public _fixedHead As Byte() = {&HAA, &H55}
|
|||
|
|
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 透传数据固定ID
|
|||
|
|
''' </summary>
|
|||
|
|
Public _fixeSystemId As Byte() = {&H54, &H33, &H53, &H41}
|
|||
|
|
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 透传数据房间信息
|
|||
|
|
''' </summary>
|
|||
|
|
Public _fixeRoomInfo As Byte() = {&HFF, &HFF, &HFF, &HFF}
|
|||
|
|
''' <summary>
|
|||
|
|
''' UDP通讯接收线程
|
|||
|
|
''' </summary>
|
|||
|
|
Private _receiveThread As Thread
|
|||
|
|
|
|||
|
|
Sub New(gControl As Control)
|
|||
|
|
|
|||
|
|
m_SerialComfig = New UDPComfig
|
|||
|
|
m_ReceiveQueue = New List(Of Cmdconfig)
|
|||
|
|
m_ReceiveQueue.Clear()
|
|||
|
|
m_Control = gControl
|
|||
|
|
|
|||
|
|
recvBufferli = New List(Of Byte)
|
|||
|
|
m_SpecialReceiveFlag = -1
|
|||
|
|
CommunicationTypeindex = 2
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
Public Overrides Sub SendData(data As Cmdconfig)
|
|||
|
|
data.CmdSendTime = DateTime.Now
|
|||
|
|
If IsNothing(m_Serial) OrElse Not m_Serial.IsBound Then
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"发送器未连接!", Color.Red), 1)
|
|||
|
|
Return
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
'清空发送缓存
|
|||
|
|
m_Serial.SendTo(data.CmdSendData, m_SerialComfig.TargetEndPoint)
|
|||
|
|
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
Public Overrides Sub CloseTransmitter()
|
|||
|
|
If Not IsNothing(m_Serial) Then
|
|||
|
|
m_Serial.Shutdown(SocketShutdown.Both)
|
|||
|
|
m_Serial.Close()
|
|||
|
|
m_Serial = Nothing
|
|||
|
|
End If
|
|||
|
|
If Not IsNothing(_receiveThread) AndAlso _receiveThread.IsAlive Then
|
|||
|
|
_receiveThread.Abort()
|
|||
|
|
End If
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
Public Overrides Sub ClearSendData()
|
|||
|
|
If IsNothing(m_ReceiveQueue) Then Return
|
|||
|
|
m_ReceiveQueue.Clear()
|
|||
|
|
End Sub
|
|||
|
|
Public Overrides Sub ClearReadData()
|
|||
|
|
|
|||
|
|
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
Public Overrides Function ReceiveData(g_comfig As Cmdconfig) As Cmdconfig
|
|||
|
|
|
|||
|
|
End Function
|
|||
|
|
''' <summary>
|
|||
|
|
''' UDP接收数据
|
|||
|
|
''' </summary>
|
|||
|
|
Private Sub UdpRecviveData()
|
|||
|
|
|
|||
|
|
Dim recvLength As Integer
|
|||
|
|
Dim recvBuffer(1024) As Byte
|
|||
|
|
|
|||
|
|
While m_Serial.IsBound
|
|||
|
|
Try
|
|||
|
|
recvLength = m_Serial.ReceiveFrom(recvBuffer, m_SerialComfig.TargetEndPoint)
|
|||
|
|
'_countRXData += recvLength
|
|||
|
|
Dim buf As Byte() = New Byte(recvLength - 1) {}
|
|||
|
|
Array.Copy(recvBuffer, buf, recvLength)
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(buf)}", Color.Blue), 1)
|
|||
|
|
Catch ex As Exception
|
|||
|
|
Console.WriteLine($"Udp Recv Error:{ex.Message}")
|
|||
|
|
Return
|
|||
|
|
End Try
|
|||
|
|
ReceivingDataProcessing(recvBuffer, recvLength)
|
|||
|
|
End While
|
|||
|
|
' If Not IsNothing(m_Transmitter) AndAlso m_Transmitter.IsTransmitter Then m_Transmitter.CloseTransmitter()
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 接收数据处理
|
|||
|
|
''' </summary>
|
|||
|
|
''' <param name="recvBuffer"></param>
|
|||
|
|
''' <param name="recvLength"></param>
|
|||
|
|
Private Sub ReceivingDataProcessing(recvBuffer() As Byte, recvLength As Integer)
|
|||
|
|
Dim startIndex As Integer '定义一个开始的计数值
|
|||
|
|
Dim packetLength As Integer '定义包的长度
|
|||
|
|
While startIndex < recvLength '判断计数值是否小于总包长
|
|||
|
|
If recvBuffer(startIndex) = _fixedHead(0) AndAlso recvBuffer(startIndex + 1) = _fixedHead(1) Then ' 判断包头是否等于AA55
|
|||
|
|
If recvBuffer(startIndex + 4) = _fixeSystemId(0) AndAlso '判断第4,5,6,7位是否等于固定值
|
|||
|
|
recvBuffer(startIndex + 5) = _fixeSystemId(1) AndAlso
|
|||
|
|
recvBuffer(startIndex + 6) = _fixeSystemId(2) AndAlso
|
|||
|
|
recvBuffer(startIndex + 7) = _fixeSystemId(3) Then
|
|||
|
|
packetLength = recvBuffer(startIndex + 2) + recvBuffer(startIndex + 3) * 256 '赋值包长
|
|||
|
|
If packetLength + startIndex <= recvLength Then '判断包长 + 计数值是否小于等于总包长
|
|||
|
|
Dim packetData(packetLength - 1) As Byte '定义一个新数据包数组
|
|||
|
|
Array.Copy(recvBuffer, startIndex, packetData, 0, packetLength) '复制数组 +5个重载
|
|||
|
|
If CheckCRC16Sucess(packetData, packetData.Length) Then '判断CRC16校验是否通过
|
|||
|
|
'显示数据
|
|||
|
|
DealData(packetData, packetLength) '分部处理数据(显示文字提示)
|
|||
|
|
startIndex += packetData.Length '计数值更新
|
|||
|
|
Else
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"CRC16校验失败!", Color.Red), 1)
|
|||
|
|
Exit While
|
|||
|
|
End If
|
|||
|
|
Else
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"数据包长校验失败!", Color.Red), 1)
|
|||
|
|
Exit While
|
|||
|
|
End If
|
|||
|
|
Else
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"数据校验失败!", Color.Red), 1)
|
|||
|
|
Exit While
|
|||
|
|
End If
|
|||
|
|
Else
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"非RCU主机发送的数据!", Color.Red), 1)
|
|||
|
|
Exit While
|
|||
|
|
End If
|
|||
|
|
End While
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 检验CRC16成功
|
|||
|
|
''' </summary>
|
|||
|
|
''' <param name="dataBuff"></param>
|
|||
|
|
''' <param name="length"></param>
|
|||
|
|
''' <returns></returns>
|
|||
|
|
Private Function CheckCRC16Sucess(dataBuff() As Byte, length As Integer) As Boolean
|
|||
|
|
Dim crcBytes() As Byte = GetCRC16CheckSum(dataBuff, length - 2)
|
|||
|
|
If crcBytes(0) <> dataBuff(length - 2) OrElse crcBytes(1) <> dataBuff(length - 1) Then Return False
|
|||
|
|
Return True
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 处理数据
|
|||
|
|
''' </summary>
|
|||
|
|
''' <param name="dataBuff"></param>
|
|||
|
|
''' <param name="length"></param>
|
|||
|
|
''' <returns></returns>
|
|||
|
|
Private Function DealData(dataBuff() As Byte, length As Integer) As Boolean
|
|||
|
|
Select Case dataBuff(8)
|
|||
|
|
Case &H70
|
|||
|
|
'获取队列第5个元素
|
|||
|
|
Dim len As Integer = m_ReceiveQueue.Count
|
|||
|
|
Dim item As Cmdconfig
|
|||
|
|
Dim buf(length - 17 - 1) As Byte
|
|||
|
|
Array.Copy(dataBuff, 15, buf, 0, buf.Length)
|
|||
|
|
|
|||
|
|
For i = 0 To len - 1
|
|||
|
|
If (len - 1 - i) < m_ReceiveQueue.Count Then
|
|||
|
|
item = m_ReceiveQueue(len - 1 - i)
|
|||
|
|
If dataBuff(15) = 2 Then
|
|||
|
|
item.OtherProtocol.UDP_TRANSPARENT_MODE_COMMAND_REPLY_STATUS = 1
|
|||
|
|
item.OtherProtocol.UDP_TRANSPARENT_MODE_COMMAND_REPLY_RESULT = dataBuff(16)
|
|||
|
|
End If
|
|||
|
|
If dataBuff(15) = 1 Then
|
|||
|
|
item.OtherProtocol.UDP_QUERY_HOST_CURRENT_MODE_COMMAND_REPLY_STATUS = 1
|
|||
|
|
item.OtherProtocol.UDP_QUERY_HOST_CURRENT_MODE_COMMAND_REPLY_RESULT = dataBuff(16)
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
'item.Protocol.ParseReceiveData(item, buf)
|
|||
|
|
End If
|
|||
|
|
Next
|
|||
|
|
Case &H71
|
|||
|
|
Dim len As Integer = m_ReceiveQueue.Count
|
|||
|
|
Dim item As Cmdconfig
|
|||
|
|
Dim buf(length - 17 - 1 - 2) As Byte
|
|||
|
|
If 17 + buf.Length < dataBuff.Length Then
|
|||
|
|
Array.Copy(dataBuff, 17, buf, 0, buf.Length)
|
|||
|
|
For i = 0 To len - 1
|
|||
|
|
If (len - 1 - i) < m_ReceiveQueue.Count Then
|
|||
|
|
item = m_ReceiveQueue(len - 1 - i)
|
|||
|
|
'If dataBuff(15) = 2 Then
|
|||
|
|
' item.OtherProtocol.UDP_TRANSPARENT_MODE_COMMAND_REPLY_STATUS = 1
|
|||
|
|
' item.OtherProtocol.UDP_TRANSPARENT_MODE_COMMAND_REPLY_RESULT = dataBuff(16)
|
|||
|
|
'End If
|
|||
|
|
'If dataBuff(15) = 1 Then
|
|||
|
|
' item.OtherProtocol.UDP_QUERY_HOST_CURRENT_MODE_COMMAND_REPLY_STATUS = 1
|
|||
|
|
' item.OtherProtocol.UDP_QUERY_HOST_CURRENT_MODE_COMMAND_REPLY_RESULT = dataBuff(16)
|
|||
|
|
'End If
|
|||
|
|
|
|||
|
|
item.Protocol.ParseReceiveData2(item, buf)
|
|||
|
|
End If
|
|||
|
|
Next
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
End Select
|
|||
|
|
Return True
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
''' <summary>
|
|||
|
|
''' 获取CRC16校验和
|
|||
|
|
''' </summary>
|
|||
|
|
''' <param name="dataBuff">数据</param>
|
|||
|
|
''' <param name="length">数据长度</param>
|
|||
|
|
''' <returns></returns>
|
|||
|
|
Private Function GetCRC16CheckSum(dataBuff() As Byte, length As Integer) As Byte()
|
|||
|
|
Dim crc16 As UInteger
|
|||
|
|
Dim crcBytes() As Byte
|
|||
|
|
|
|||
|
|
crc16 = &HFFFF
|
|||
|
|
For i = 0 To length - 1
|
|||
|
|
crc16 = crc16 And &HFFFF
|
|||
|
|
crc16 = crc16 Xor dataBuff(i)
|
|||
|
|
For bit = 0 To 7
|
|||
|
|
crc16 = IIf((crc16 And 1) = 0, crc16 >> 1, (crc16 >> 1) Xor &HA001)
|
|||
|
|
Next
|
|||
|
|
Next
|
|||
|
|
crc16 = crc16 And &HFFFF
|
|||
|
|
crcBytes = BitConverter.GetBytes(UShort.Parse(crc16))
|
|||
|
|
Return crcBytes
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
Public Overrides Function IsTransmitter() As Boolean
|
|||
|
|
If IsNothing(m_Serial) OrElse m_Serial.Connected = False Then Return False
|
|||
|
|
Return True
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
Public Overrides Function OpenTransmitter() As Boolean
|
|||
|
|
If Not IsNothing(m_Serial) Then
|
|||
|
|
m_Serial.Shutdown(SocketShutdown.Both)
|
|||
|
|
m_Serial.Close()
|
|||
|
|
End If
|
|||
|
|
If Not IsNothing(_receiveThread) AndAlso _receiveThread.IsAlive Then
|
|||
|
|
_receiveThread.Abort()
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
m_Serial = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
|
|||
|
|
''加保护机制
|
|||
|
|
m_Serial.Bind(m_SerialComfig.LocalEndPoint)
|
|||
|
|
m_Serial.Connect(m_SerialComfig.TargetEndPoint)
|
|||
|
|
_receiveThread = New Thread(New ThreadStart(AddressOf UdpRecviveData))
|
|||
|
|
_receiveThread.Start()
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
Public Overrides Function GetTransmitterStatus() As Boolean
|
|||
|
|
If IsNothing(m_Serial) Then Return False
|
|||
|
|
Return True
|
|||
|
|
End Function
|
|||
|
|
''' <summary>
|
|||
|
|
''' 本地ip/本地端口/目标ip/目标端口
|
|||
|
|
''' </summary>
|
|||
|
|
''' <param name="params"></param>
|
|||
|
|
''' <returns></returns>
|
|||
|
|
Public Overrides Function SetTransmitterParameter(ParamArray params() As Object) As Boolean
|
|||
|
|
If IsNothing(m_SerialComfig) Then Return False
|
|||
|
|
Dim ipAddr As IPAddress
|
|||
|
|
Dim port As Integer
|
|||
|
|
If params.Length > 0 Then
|
|||
|
|
'判断是否为ip
|
|||
|
|
If IPAddress.TryParse(params(0), ipAddr) Then
|
|||
|
|
m_SerialComfig.LocalIP = ipAddr
|
|||
|
|
End If
|
|||
|
|
If params.Length > 1 Then
|
|||
|
|
'判断是否为端口
|
|||
|
|
If Integer.TryParse(params(1), port) Then
|
|||
|
|
m_SerialComfig.LocalPort = port
|
|||
|
|
End If
|
|||
|
|
End If
|
|||
|
|
If params.Length > 2 Then
|
|||
|
|
'判断是否为ip
|
|||
|
|
If IPAddress.TryParse(params(2), ipAddr) Then
|
|||
|
|
m_SerialComfig.TargetIP = ipAddr
|
|||
|
|
End If
|
|||
|
|
If params.Length > 3 Then
|
|||
|
|
'判断是否为端口
|
|||
|
|
If Integer.TryParse(params(3), port) Then
|
|||
|
|
m_SerialComfig.TargetPort = port
|
|||
|
|
End If
|
|||
|
|
End If
|
|||
|
|
End If
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
'判断本地ip和 端口是否有效
|
|||
|
|
If IsNothing(m_SerialComfig.LocalIP) OrElse IsNothing(m_SerialComfig.LocalPort) Then
|
|||
|
|
MsgBox("本地ip或端口无效")
|
|||
|
|
Else
|
|||
|
|
'判断目标ip和 端口是否有效
|
|||
|
|
m_SerialComfig.LocalEndPoint = New IPEndPoint(m_SerialComfig.LocalIP, m_SerialComfig.LocalPort)
|
|||
|
|
End If
|
|||
|
|
'判断目标ip和 端口是否有效
|
|||
|
|
If IsNothing(m_SerialComfig.TargetIP) OrElse IsNothing(m_SerialComfig.TargetPort) Then
|
|||
|
|
MsgBox("目标ip或端口无效")
|
|||
|
|
Else
|
|||
|
|
m_SerialComfig.TargetEndPoint = New IPEndPoint(m_SerialComfig.TargetIP, m_SerialComfig.TargetPort)
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
End Function
|
|||
|
|
'判断是否为端口
|
|||
|
|
Private Function IsPort(port As String) As Boolean
|
|||
|
|
Return Integer.TryParse(port, port)
|
|||
|
|
End Function
|
|||
|
|
'判断是否为ip
|
|||
|
|
Private Function IsIP(ip As String) As Boolean
|
|||
|
|
Dim ipAddr As IPAddress
|
|||
|
|
Return IPAddress.TryParse(ip, ipAddr)
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
Public Overrides Function SendData(data() As Byte) As Boolean
|
|||
|
|
'data.CmdSendTime = DateTime.Now
|
|||
|
|
If IsNothing(m_Serial) Then
|
|||
|
|
RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"发送器未连接!", Color.Red), 1)
|
|||
|
|
Return False
|
|||
|
|
End If
|
|||
|
|
|
|||
|
|
'清空发送缓存
|
|||
|
|
m_Serial.SendTo(data, m_SerialComfig.TargetEndPoint)
|
|||
|
|
Return True
|
|||
|
|
End Function
|
|||
|
|
End Class
|
|||
|
|
Public Class UDPComfig
|
|||
|
|
'本地ip
|
|||
|
|
Public LocalIP As IPAddress
|
|||
|
|
'本地端口
|
|||
|
|
Public LocalPort As Integer
|
|||
|
|
'目标ip
|
|||
|
|
Public TargetIP As IPAddress
|
|||
|
|
'目标端口
|
|||
|
|
Public TargetPort As Integer
|
|||
|
|
'发送网络端点
|
|||
|
|
Public LocalEndPoint As IPEndPoint
|
|||
|
|
'接收网络端点
|
|||
|
|
Public TargetEndPoint As IPEndPoint
|
|||
|
|
|
|||
|
|
'获取 串口名称列表
|
|||
|
|
Sub New()
|
|||
|
|
LocalIP = GetLocalIP.Item(0)
|
|||
|
|
|
|||
|
|
End Sub
|
|||
|
|
|
|||
|
|
'获取本地IP列表
|
|||
|
|
Public Shared Function GetLocalIP() As List(Of IPAddress)
|
|||
|
|
Dim address() As IPAddress
|
|||
|
|
Dim destAddress As New List(Of IPAddress)
|
|||
|
|
address = Dns.GetHostEntry(Dns.GetHostName()).AddressList
|
|||
|
|
For Each pAddress As IPAddress In address
|
|||
|
|
If pAddress.AddressFamily = AddressFamily.InterNetwork Then
|
|||
|
|
destAddress.Add(pAddress)
|
|||
|
|
End If
|
|||
|
|
Next
|
|||
|
|
Return destAddress
|
|||
|
|
End Function
|
|||
|
|
|
|||
|
|
End Class
|