Files
Desktop_NTCAM_Controller/CommunicationProtocol/CommunicationProtocol.vb

520 lines
18 KiB
VB.net
Raw Normal View History

2025-12-11 13:59:46 +08:00
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