520 lines
18 KiB
VB.net
520 lines
18 KiB
VB.net
Imports System.IO.Ports
|
||
Imports System.Threading
|
||
Imports NT_CAM_Controller.SendNode
|
||
|
||
Public Class CommunicationProtocol
|
||
'流程列表
|
||
Public Property FlowList As List(Of (String, SendNode))
|
||
Public IsFlowList As Boolean
|
||
'执行流程任务线程
|
||
Public Property FlowThread As Task
|
||
Public IsFlowThread As Boolean
|
||
Public G_RichTextPrint As RichTextPrint
|
||
Public G_Transmitter As SerialPort
|
||
Public ControlDic As New Dictionary(Of Integer, Control)
|
||
|
||
Sub New(RichTextPrint As RichTextPrint, gTransmitter As SerialPort)
|
||
|
||
FlowList = New List(Of (String, SendNode))
|
||
G_RichTextPrint = RichTextPrint
|
||
G_Transmitter = gTransmitter
|
||
'初始化FlowThread
|
||
IsFlowThread = True
|
||
FlowThread = New Task(AddressOf FlowThreadRun)
|
||
FlowThread.Start()
|
||
IsFlowList = False
|
||
ControlDic = New Dictionary(Of Integer, Control)
|
||
End Sub
|
||
|
||
'添加控件列表
|
||
Sub AddControlDic(ControlName As Integer, Control As Control)
|
||
If IsNothing(ControlDic) Then ControlDic = New Dictionary(Of Integer, Control)
|
||
If ControlDic.ContainsKey(ControlName) Then
|
||
ControlDic.Item(ControlName) = Control
|
||
Else
|
||
ControlDic.Add(ControlName, Control)
|
||
End If
|
||
|
||
End Sub
|
||
|
||
|
||
'关闭
|
||
Sub Close()
|
||
If FlowThread Is Nothing OrElse Not FlowThread.IsCompleted Then Return
|
||
FlowThread.Dispose()
|
||
End Sub
|
||
|
||
'关闭线程
|
||
Sub CloseThread()
|
||
If FlowThread Is Nothing OrElse Not FlowThread.IsCompleted Then Return
|
||
FlowThread.Dispose()
|
||
End Sub
|
||
'设置IsFlowThread
|
||
Sub SetIsFlowThread(mIsFlowThread As Boolean)
|
||
Me.IsFlowThread = mIsFlowThread
|
||
End Sub
|
||
Sub setIsFlowList(mIsFlowList As Boolean)
|
||
Me.IsFlowList = mIsFlowList
|
||
End Sub
|
||
|
||
Public Function getIsFlowList() As Boolean
|
||
Return False
|
||
Return Me.IsFlowList
|
||
End Function
|
||
Public Function getIsFlowList1() As Boolean
|
||
|
||
Return Me.IsFlowList
|
||
End Function
|
||
'执行流程任务
|
||
Sub FlowThreadRun()
|
||
'流程节点执行状态
|
||
Dim isnode As Boolean
|
||
Dim nli As New List(Of Integer)
|
||
While IsFlowThread
|
||
Thread.Sleep(1)
|
||
If IsNothing(FlowList) OrElse FlowList.Count = 0 Then
|
||
'延时100ms
|
||
Thread.Sleep(100)
|
||
Else
|
||
If IsFlowList Then
|
||
nli.Clear()
|
||
Dim FlowListCount As Integer = FlowList.Count
|
||
Console.WriteLine("FlowListCount:" & FlowListCount)
|
||
' For Each node In FlowList
|
||
For i As Integer = 0 To FlowListCount - 1
|
||
If Not IsFlowList Then
|
||
Exit For
|
||
End If
|
||
|
||
Dim node As (String, SendNode) = FlowList(i)
|
||
|
||
'判断本包是否超时接收
|
||
If (node.Item2.SendCount >= node.Item2.MaxResendCount) OrElse node.Item2.RecvStatus = 1 Then
|
||
nli.Add(i)
|
||
Continue For
|
||
End If
|
||
|
||
If IsFlowThread = False Then Exit For
|
||
While node.Item2.RecvStatus = SendNode.RecvStatusEnum.None
|
||
If Not node.Item2.IsRecvData Then
|
||
node.Item2.RecvRefresh(Nothing)
|
||
End If
|
||
If IsFlowThread = False Then Exit For
|
||
'判断是什么类型命令
|
||
If node.Item2.CommandType = 0 Then
|
||
'系统命令
|
||
isnode = SystemCommandSelector(node.Item1, node.Item2)
|
||
If isnode = False Then
|
||
'MsgBox(node.Item2.TipInfo)
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig(node.Item2.TipInfo, Color.Red), 1)
|
||
'IsFlowList = False
|
||
Exit While
|
||
Else
|
||
Exit While
|
||
End If
|
||
|
||
Else
|
||
'自定义命令
|
||
isnode = CustomCommandSelector(node.Item1, node.Item2)
|
||
If isnode = False Then
|
||
nli.Add(i)
|
||
'MsgBox(node.Item2.TipInfo)
|
||
'G_RichTextPrint.AddQueue(New RichTextNodeConfig(node.Item2.TipInfo, Color.Red), 1)
|
||
'IsFlowList = False
|
||
'Else
|
||
Exit While
|
||
Else
|
||
'Exit While
|
||
End If
|
||
End If
|
||
|
||
|
||
End While
|
||
Next
|
||
|
||
|
||
|
||
'从大到小删除
|
||
For Each i In nli.OrderByDescending(Function(x) x)
|
||
If Not IsFlowList Then
|
||
Exit For
|
||
End If
|
||
FlowList.RemoveAt(i)
|
||
Next
|
||
IsFlowList = False
|
||
Console.WriteLine($"流程节点数量:{FlowList.Count}")
|
||
End If
|
||
End If
|
||
End While
|
||
End Sub
|
||
'系统命令选择器
|
||
Public Function SystemCommandSelector(nodename As String, ByRef mSendNode As SendNode) As Boolean
|
||
If mSendNode.SendData.Length > 0 Then
|
||
Select Case mSendNode.SendData(0)
|
||
Case 1 '系统延时
|
||
If mSendNode.SendData.Length > 1 Then
|
||
mSendNode.ResendRefresh()
|
||
Thread.Sleep(mSendNode.SendData(1))
|
||
mSendNode.RecvRefresh({mSendNode.SendData(1)})
|
||
mSendNode.SetTipInfo("执行延时完成!")
|
||
Return True
|
||
Else
|
||
mSendNode.SetTipInfo($"{nodename}参数异常!")
|
||
Return False
|
||
End If
|
||
|
||
End Select
|
||
Else
|
||
|
||
mSendNode.SetTipInfo("系统命令参数异常!")
|
||
Return False
|
||
End If
|
||
End Function
|
||
|
||
|
||
'自定义命令选择器
|
||
Public Function CustomCommandSelector(nodename As String, ByRef mSendNode As SendNode) As Boolean
|
||
Dim sendbuf As Byte()
|
||
If mSendNode.SendStatus = SendNode.SendStatusEnum.None Then
|
||
sendbuf = SendPortData1(nodename, mSendNode)
|
||
If IsNothing(sendbuf) OrElse sendbuf.Length = 0 Then
|
||
Return False
|
||
Else
|
||
Return SendPortData(nodename, mSendNode, sendbuf, G_Transmitter)
|
||
End If
|
||
|
||
Else
|
||
'判断节点是否需要重新发送
|
||
If mSendNode.NeedResend() Then
|
||
|
||
sendbuf = SendPortData1(nodename, mSendNode)
|
||
If IsNothing(sendbuf) OrElse sendbuf.Length = 0 Then
|
||
Return False
|
||
Else
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig($"第{mSendNode.SendCount}次重发数据", Color.Black), 1)
|
||
Return SendPortData(nodename, mSendNode, sendbuf, G_Transmitter)
|
||
End If
|
||
Else
|
||
If mSendNode.SendCount < mSendNode.MaxResendCount Then
|
||
|
||
ElseIf mSendNode.SendCount = mSendNode.MaxResendCount Then
|
||
If mSendNode.SendTime.AddMilliseconds(mSendNode.SendTimeout) < Now Then
|
||
mSendNode.SendCount = mSendNode.SendCount + 1
|
||
|
||
Else
|
||
|
||
End If
|
||
Else
|
||
mSendNode.RecvStatus = RecvStatusEnum.Timeout
|
||
mSendNode.SendStatus = SendStatusEnum.Timeout
|
||
' IsRuningTest = False '退出流程
|
||
'RefreshCaptureText(Color.Red, $"节点:{node.Item1} :发送失败!")
|
||
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig($"发数据超时!", Color.Red), 1)
|
||
mSendNode.SetTipInfo($"发数据超时!")
|
||
Return False
|
||
End If
|
||
End If
|
||
Return True
|
||
End If
|
||
End Function
|
||
'获取发送数据
|
||
Public Function SendPortData1(nodename As String, Mysenddata As SendNode) As Byte()
|
||
If IsNothing(Mysenddata) OrElse Mysenddata.SendData.Length = 0 Then Return Nothing
|
||
Return Mysenddata.SendData
|
||
End Function
|
||
'发送数据
|
||
Public Function SendPortData(nodename As String, ByRef Mysenddata As SendNode, sendBytes As Byte(), mTransmitter As SerialPort) As Boolean
|
||
If IsNothing(G_Transmitter) OrElse G_Transmitter.IsOpen = False Then
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("发送器未打开!", Color.Red), 1)
|
||
Return False
|
||
End If
|
||
Try
|
||
'发送数据
|
||
Mysenddata.SetSendData(sendBytes, Mysenddata.SendTimeout)
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("TX:", Color.Blue, New Font("宋体", 8), Mysenddata.SendData), 1)
|
||
G_Transmitter.Write(Mysenddata.SendData, 0, Mysenddata.SendData.Length)
|
||
'发送刷新对应数值
|
||
Mysenddata.ResendRefresh()
|
||
Return True
|
||
Catch ex As Exception
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("发送器发送异常!", Color.Red), 1)
|
||
Return False
|
||
End Try
|
||
|
||
End Function
|
||
Public Function SendPortData(sendBytes As Byte(), mTransmitter As SerialPort) As Boolean
|
||
If IsNothing(G_Transmitter) OrElse G_Transmitter.IsOpen = False Then
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("发送器未打开!", Color.Red), 1)
|
||
Return False
|
||
End If
|
||
Try
|
||
'发送数据
|
||
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("TX:", Color.Blue, New Font("宋体", 8), sendBytes), 1)
|
||
G_Transmitter.Write(sendBytes, 0, sendBytes.Length)
|
||
'发送刷新对应数值
|
||
|
||
Return True
|
||
Catch ex As Exception
|
||
G_RichTextPrint.AddQueue(New RichTextNodeConfig("发送器发送异常!", Color.Red), 1)
|
||
Return False
|
||
End Try
|
||
|
||
End Function
|
||
|
||
|
||
'添加流程节点
|
||
Public Function AddFlowNode(nodename As String, Mysenddata As SendNode) As Boolean
|
||
If FlowList Is Nothing Then Return False
|
||
FlowList.Add((nodename, Mysenddata))
|
||
End Function
|
||
'清空流程节点
|
||
Public Function ClearFlowNode(Optional isclear As Boolean = False) As Boolean
|
||
If FlowList Is Nothing Then Return False
|
||
If isclear Then
|
||
FlowList.Clear()
|
||
End If
|
||
'FlowList.Clear()
|
||
End Function
|
||
|
||
|
||
'处理接收到的数据
|
||
Public Function ProcessRecvData(RecvData() As Byte) As Boolean
|
||
If FlowList Is Nothing Then Return False
|
||
'判断数据包头是否合法
|
||
If NT_CAM.IsDataValid(RecvData) Then
|
||
If RecvData(3) >= &HB0 Then
|
||
Dim sendbuf = NT_CAM.PackData(RecvData(3), {0})
|
||
SendPortData(sendbuf, G_Transmitter)
|
||
ElseIf RecvData(3) >= &H10 AndAlso RecvData(3) < &HA0 Then
|
||
|
||
|
||
|
||
Select Case RecvData(3)
|
||
Case &H18
|
||
Dim sendbuf = NT_CAM.PackData(RecvData(3), {0})
|
||
SendPortData(sendbuf, G_Transmitter)
|
||
Dim mControl As Control = ControlDic.Item(&H18)
|
||
If RecvData(6) = 0 Then
|
||
SharedFunction.SetFromUI(mControl, "未连接", Color.Black, Color.Red)
|
||
ElseIf RecvData(6) = 1 Then
|
||
SharedFunction.SetFromUI(mControl, "已连接", Color.Black, Color.Green)
|
||
Else
|
||
SharedFunction.SetFromUI(mControl, "连接异常", Color.Black, Color.Red)
|
||
End If
|
||
Return True
|
||
Case &H19
|
||
Dim mControl As Control = ControlDic.Item(&H19)
|
||
Dim sendbuf = NT_CAM.PackData(RecvData(3), {0})
|
||
SendPortData(sendbuf, G_Transmitter)
|
||
'获取数据长度
|
||
Dim len As Integer = RecvData(5) * 256 + RecvData(4)
|
||
'判断数据长度是否合法 且长度能够取到
|
||
If len > 0 AndAlso len <= RecvData.Length - 6 Then
|
||
'获取数据
|
||
Dim data As Byte() = New Byte(len - 1) {}
|
||
Array.Copy(RecvData, 6, data, 0, len)
|
||
'将数组转换为字符串
|
||
Dim str As String = SharedFunction.ByteToHexString(data)
|
||
SharedFunction.SetFromUI(mControl, str, Color.Black, Color.White)
|
||
End If
|
||
Return True
|
||
|
||
|
||
End Select
|
||
|
||
|
||
|
||
|
||
Dim node As SendNode
|
||
Dim nextNode As SendNode
|
||
For i = 0 To FlowList.Count - 1
|
||
node = FlowList(i).Item2
|
||
If node.SendStatus = SendNode.SendStatusEnum.Send Then
|
||
If node.RecvStatus = SendNode.RecvStatusEnum.None Then
|
||
If RecvData(3) = node.SendData(3) Then
|
||
node.RecvRefresh(RecvData)
|
||
End If
|
||
|
||
End If
|
||
End If
|
||
Next
|
||
|
||
|
||
Else
|
||
Dim node As SendNode
|
||
Dim nextNode As SendNode
|
||
For i = 0 To FlowList.Count - 1
|
||
node = FlowList(i).Item2
|
||
If node.SendStatus = SendNode.SendStatusEnum.Send Then
|
||
If node.RecvStatus = SendNode.RecvStatusEnum.None Then
|
||
If RecvData(3) = node.SendData(3) Then
|
||
node.RecvRefresh(RecvData)
|
||
End If
|
||
|
||
End If
|
||
End If
|
||
Next
|
||
End If
|
||
|
||
End If
|
||
|
||
End Function
|
||
|
||
|
||
|
||
|
||
|
||
End Class
|
||
|
||
Public Class SendNode
|
||
'命令类型
|
||
Public Property CommandType As Integer '0:系统命令,1:自定义命令
|
||
|
||
'发送时间
|
||
Public Property SendTime As DateTime
|
||
'发送数据
|
||
Public Property SendData As Byte()
|
||
'重发次数
|
||
Public Property SendCount As Integer
|
||
'重发间隔
|
||
Public Property SendInterval As Integer
|
||
'超时时间
|
||
Public Property SendTimeout As Integer
|
||
'发送状态 0:未发送 1:已发送
|
||
Public Property SendStatus As Integer
|
||
'接收状态
|
||
Public Property RecvStatus As Integer
|
||
'接收数据
|
||
Public Property RecvDataLisr As List(Of Byte())
|
||
|
||
'提示信息
|
||
Public Property TipInfo As String
|
||
|
||
'最大重 发次数
|
||
Public Property MaxResendCount As Integer
|
||
|
||
'是否接收数据
|
||
Public Property IsRecvData As Boolean
|
||
'控件对象
|
||
Public Property Control As Control
|
||
|
||
''' <summary>
|
||
''' 命令
|
||
''' </summary>
|
||
''' <param name="mCommandType"></param>
|
||
Sub New(mCommandType As Integer, Optional mMaxResendCoun As Integer = 3)
|
||
CommandType = mCommandType
|
||
RecvDataLisr = New List(Of Byte())
|
||
MaxResendCount = mMaxResendCoun
|
||
IsRecvData = True
|
||
End Sub
|
||
|
||
'设置控件
|
||
Sub SetControl(mControl As Control)
|
||
Control = mControl
|
||
End Sub
|
||
|
||
'发送状态枚举值
|
||
Enum SendStatusEnum
|
||
'未发送
|
||
None = 0
|
||
'已发送
|
||
Send = 1
|
||
'发送超时
|
||
Timeout = 2
|
||
End Enum
|
||
|
||
'接收状态枚举值
|
||
Enum RecvStatusEnum
|
||
'未接收
|
||
None = 0
|
||
'已接收
|
||
Recv = 1
|
||
'接收超时
|
||
Timeout = 2
|
||
End Enum
|
||
|
||
Sub New(Mysenddata() As Byte)
|
||
SendData = Mysenddata
|
||
SendInterval = 0
|
||
SendTimeout = 1000
|
||
RecvStatus = 0
|
||
SendStatus = 0
|
||
RecvDataLisr = New List(Of Byte())
|
||
End Sub
|
||
'设置发送数据
|
||
Sub SetSendData(Mysenddata() As Byte, Optional gSendTimeout As Integer = 1000)
|
||
SendData = Mysenddata
|
||
SendInterval = 0
|
||
SendTimeout = gSendTimeout
|
||
RecvStatus = 0
|
||
SendStatus = 0
|
||
End Sub
|
||
|
||
'接收数据并添加到接收列表
|
||
Sub AddRecvData(RecvData() As Byte)
|
||
If RecvDataLisr Is Nothing Then
|
||
RecvDataLisr = New List(Of Byte())
|
||
End If
|
||
RecvDataLisr.Add(RecvData)
|
||
End Sub
|
||
'判断需不需要重发 False 不需要重发 True 需要重发
|
||
Function NeedResend() As Boolean
|
||
'如果接收状态为已加收, 则不需要重发
|
||
If SendStatus = 1 AndAlso RecvStatus = 1 Then
|
||
Return False
|
||
Else
|
||
'如果发送状态为已发送,则判断是否超时,如果超时则返回True,否则返回False
|
||
If SendStatus = 1 Then
|
||
'判断是否到达最大重发次数
|
||
If SendCount < MaxResendCount Then
|
||
|
||
If SendTime.AddMilliseconds(SendTimeout) < Now Then
|
||
Return True
|
||
Else
|
||
Return False
|
||
End If
|
||
|
||
Else
|
||
|
||
'RecvStatus = RecvStatusEnum.Timeout
|
||
'SendStatus = SendStatusEnum.Timeout
|
||
Return False
|
||
End If
|
||
Else
|
||
Return True
|
||
End If
|
||
|
||
End If
|
||
|
||
End Function
|
||
|
||
'重发刷新对应数值
|
||
Sub ResendRefresh()
|
||
SendStatus = 1
|
||
SendCount += 1
|
||
SendTime = Now
|
||
End Sub
|
||
|
||
'发送刷新对应数值
|
||
Sub SendRefresh()
|
||
SendStatus = 1
|
||
SendTime = Now
|
||
SendCount = 0
|
||
End Sub
|
||
'接收刷新对应数值
|
||
Sub RecvRefresh(Mysenddata() As Byte)
|
||
AddRecvData(Mysenddata)
|
||
RecvStatus = 1
|
||
End Sub
|
||
|
||
'设置提示信息
|
||
Sub SetTipInfo(Mysenddata As String)
|
||
TipInfo = Mysenddata
|
||
End Sub
|
||
|
||
|
||
End Class
|