Files
Desktop_NT318VTool_V02/Form1.vb
2025-12-11 13:49:44 +08:00

3625 lines
137 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Imports System.IO
Imports System.Reflection.Emit
Imports System.Threading
Imports System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock
Imports System.Text
Imports FlexCell
Imports Newtonsoft.Json
Imports System.Data.Common
Imports System.Data.SQLite
Imports System.Net
Public Class Form1
#Region "初始化"
''' <summary>
''' 项目加载事件
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Text += "(" & Application.ProductVersion & ")"
If Not String.IsNullOrEmpty(My.Settings.SerialPortName) Then
My.Settings.Reload()
ComboBox8.Text = My.Settings.SerialPortName
ToolStripTextBox1.Text = My.Settings.SInTime
End If
'将 和执行文件同目录的CommandSetDic.flx文件拷贝到 C盘C: \NT2406_Tool 下
'判断C: \NT2406_Tool 存不存在
If Not IO.Directory.Exists(FileCPatrh) Then
IO.Directory.CreateDirectory(FileCPatrh)
End If
' 判断文件是否存在($"{Application.StartupPath }\CommandSetDic.flx")
If IO.File.Exists($"{Application.StartupPath }\CommandSetDic.flx") Then
'判断文件是否存在
If IO.File.Exists($"{FileCPatrh}\CommandSetDic.flx") Then
Else
'文件拷贝到C: \NT2406_Tool 下
IO.File.Copy($"{Application.StartupPath }\CommandSetDic.flx", $"{FileCPatrh}\CommandSetDic.flx", True)
End If
Else
MessageBox.Show("CommandSetDic.flx 文件损坏")
Me.Close()
End If
'(FileCPatrh & "\CommandSetDic.flx"
InitSerialPortBaud()
Grid_Format_initial()
Show_Device_Setinfo_Info()
ClearDeviceform()
InitGrid_table()
InitLoadProcessTable()
InitCommandSetDic()
ToolStripButton2.PerformClick()
Timer2.Start()
End Sub
#End Region
#Region "串口通信"
''' <summary>
''' 当前时间
''' </summary>
Private _nowTime As Date
''' <summary>
''' 最后时间
''' </summary>
Private _lastTime As Date
''' <summary>
''' 时间间隔
''' </summary>
Private _timeInterbval As TimeSpan
''' <summary>
''' 接收数据偏移量
''' </summary>
Private _recvOffset As Integer
''' <summary>
''' 接收数据缓存包
''' </summary>
Private _recvBuffer(254) As Byte
''' <summary>
''' 串口波特率
''' </summary>
Private _baudItme() As String = {"4800", "9600", "14400", "19200", "38400", "56000", "57600", "115200", "256000", "512000", "600000", "750000"}
Public DbConnString As String = "Server=blv-cloud-db.mysql.rds.aliyuncs.com;Port=3307;Database=blv_productionlinetest;Uid=blv_rcu;Pwd=fnadiaJDIJ7546;charset=utf8;"
Enum TableEnum
ID = 0
测试时间
测试结果
测试信息
RTC时间
RTC星期
校准结果
稳定消抖时间_秒
背景值滤波长度_秒
传感器极大值
传感器极小值
预热时间_分
ADC_LEV_10
ADC_LEV_0
触发_消抖次数
释放_消抖次数
稳定阈值
报警点提前量
校准超时_秒
校准最小值_LEV_0
校准最小值_LEV_10
校准最小值_差值
校准最大值_LEV_0
校准最大值_LEV_10
校准最大值_差值
泄露恢复正常_条件1
泄露恢复正常_条件2
泄露恢复正常_条件1消抖时间_秒
泄露恢复正常_条件2消抖时间_分
设备生产时间
软件版本号
硬件版本号
设备类型ID
厂牌ID
机型ID
UUID
状态机
实时值
背景值
基底值
差值
LEL百分比
稳定状态
基底值差值百分比1
基底值差值百分比2
温度
服务器key
服务器ClientId
设备key
设备ClientId
MAX
End Enum
'获取表格枚举值名称
Private Function GetTableEnumName(tableEnum As TableEnum) As String
Return [Enum].GetName(GetType(TableEnum), tableEnum)
End Function
''' <summary>
''' 初始化串口波特率
''' </summary>
Private Sub InitSerialPortBaud()
ComboBox9.Items.Clear()
ComboBox9.Items.AddRange(_baudItme)
If ComboBox9.Items.Count > 1 Then ComboBox9.SelectedIndex = 0
End Sub
''' <summary>
''' 选择串口
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub ComboBox8_DropDown(sender As Object, e As EventArgs) Handles ComboBox8.DropDown
GetSerialPort()
End Sub
''' <summary>
''' 串口通信
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button19_Click(sender As Object, e As EventArgs) Handles Button19.Click
' RichTextBox1.Text = Application.ProductName
If String.IsNullOrWhiteSpace(ComboBox8.Text) Then
MsgBox($"请先选择有效串口!")
Exit Sub
End If
If String.IsNullOrWhiteSpace(ComboBox9.Text) Then
MsgBox($"请先选择有效波特率!")
Exit Sub
End If
SerialPortCommSwitch(ComboBox8.Text, ComboBox9.Text)
End Sub
''' <summary>
''' 获取可用串口
''' </summary>
Private Sub GetSerialPort()
Dim portNames As String() = Ports.SerialPort.GetPortNames '获得可用串口
Array.Sort(portNames)
ComboBox8.Items.Clear()
ComboBox8.Items.AddRange(portNames)
End Sub
''' <summary>
''' 串口通讯开关
''' </summary>
''' <param name="portName"></param>
''' <param name="portBaud"></param>
Private Sub SerialPortCommSwitch(portName As String, portBaud As String)
If SerialPort.IsOpen Then
SerialPort.Close()
CloseSerialPort()
Else
ConfigSerialPort(portName, portBaud)
Try
SerialPort.Open()
OpenSerialPort()
Catch ex As Exception
'Console.WriteLine($"串口打开失败,原因:{ex.Message}" & vbCrLf, Color.Red)
MsgBox($"串口打开失败,原因:{ex.Message}")
SerialPort.Close()
CloseSerialPort()
End Try
End If
End Sub
''' <summary>
''' 关闭串口
''' </summary>
Private Sub CloseSerialPort()
ComboBox8.Enabled = True
ComboBox9.Enabled = True
Button19.Text = $"打开串口"
Button19.ForeColor = Color.Green
End Sub
''' <summary>
''' 配置串口
''' </summary>
''' <param name="portName">串口名</param>
''' <param name="portBaud">串口波特率</param>
Public Sub ConfigSerialPort(portName As String, portBaud As String)
With SerialPort
.PortName = portName '串口名
.BaudRate = CInt(portBaud) '波特率
.DataBits = 8 '数据位
.StopBits = Ports.StopBits.One '停止位
.Parity = Ports.Parity.Even '偶校验
.RtsEnable = True
.ReceivedBytesThreshold = 1
End With
End Sub
''' <summary>
''' 打开串口
''' </summary>
Private Sub OpenSerialPort()
ComboBox8.Enabled = False
ComboBox9.Enabled = False
Button19.Text = $"关闭串口"
Button19.ForeColor = Color.Red
End Sub
''' <summary>
''' 发送485串口数据
''' </summary>
''' <param name="dataBuff"></param>
''' <returns></returns>
Private Function SendPortData(dataBuff() As Byte)
Dim portData As String = ByteToString(dataBuff)
Dim timeData As String
Dim cutTime As String
_nowTime = Now
_timeInterbval = _nowTime - _lastTime
_lastTime = _nowTime
timeData = $"{Math.Round(_timeInterbval.TotalMilliseconds, 0)}"
timeData = timeData.PadRight(6)
cutTime = $"{Now:HH:mm:ss:fff}"
Try
SerialPort.Write(dataBuff, 0, dataBuff.Length)
AppendTipText("Com-TX:", Color.Green)
AppendTipText("(" & cutTime & "-", Color.Black)
AppendTipText(timeData, Color.BlueViolet)
AppendTipText("):", Color.Black)
AppendTipText(portData & vbCrLf, Color.Green)
Catch ex As Exception
MsgBox($"串口发送错误!原因:{ex.Message}")
AppendTipText($"串口发送错误!原因:{ex.Message}", Color.Red)
Return False
End Try
Return True
End Function
Private Function SendPortData(dataBuff() As Byte, dataLen As Integer)
Dim portData As String = ByteToString(dataBuff, dataLen)
Dim timeData As String
Dim cutTime As String
_nowTime = Now
_timeInterbval = _nowTime - _lastTime
_lastTime = _nowTime
timeData = $"{Math.Round(_timeInterbval.TotalMilliseconds, 0)}"
timeData = timeData.PadRight(6)
cutTime = $"{Now:HH:mm:ss:fff}"
Try
SerialPort.Write(dataBuff, 0, dataLen)
AppendTipText("Com-TX:", Color.Green)
AppendTipText("(" & cutTime & "-", Color.Black)
AppendTipText(timeData, Color.BlueViolet)
AppendTipText("):", Color.Black)
AppendTipText(portData & vbCrLf, Color.Green)
Catch ex As Exception
MsgBox($"串口发送错误!原因:{ex.Message}")
AppendTipText($"串口发送错误!原因:{ex.Message}", Color.Red)
Return False
End Try
Return True
End Function
''' <summary>
''' 接收485串口数据
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub SerialPort_DataReceived(sender As Object, e As Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Static bytes As Integer
_recvOffset = 0
Try
Do
bytes = SerialPort.BytesToRead
If bytes <= 0 Then Exit Sub
If bytes + _recvOffset >= 255 Then
SerialPort.Read(_recvBuffer, _recvOffset, 255 - _recvOffset)
ShowPortReceData(_recvBuffer)
If IsRuningTest Then
ProcessAnalyticalData(_recvBuffer)
Else
If AnalyticalData(_recvBuffer) = &H1 Then
AppendTipText(Encoding.UTF8.GetString(_recvBuffer) & vbCrLf, Color.Green)
End If
End If
_recvOffset = 0
Else
SerialPort.Read(_recvBuffer, _recvOffset, bytes)
_recvOffset += bytes
End If
Thread.Sleep(10)
Loop While SerialPort.BytesToRead > 0
If _recvOffset > 0 Then
Dim buf(_recvOffset - 1) As Byte
Array.Copy(_recvBuffer, 0, buf, 0, buf.Length)
ShowPortReceData(buf)
If IsRuningTest Then
ProcessAnalyticalData(_recvBuffer)
Else
If AnalyticalData(_recvBuffer) = &H1 Then
AppendTipText(Encoding.UTF8.GetString(buf) & vbCrLf, Color.Green)
End If
End If
End If
Catch ex As Exception
AppendTipText($"串口接收数据失败,原因:{ex.Message}", Color.Red)
End Try
End Sub
'处理串口接收函数
Private Function ProcessAnalyticalData(databuff() As Byte) As Byte
'For Each node In SendNodeDic
' If IsRuningTest = False Then Return
If databuff(0) = &HF0 Then
If databuff(1) = &HF0 Then
If databuff(2) = &HF0 Then
If databuff(3) = &HF0 Then
Dim temp_val As Integer = 0
'产品状态
Show_Device_Work_State(databuff(4))
'浓度状态
temp_val = databuff(5)
temp_val <<= 8
temp_val += databuff(6)
'Show_Device_GasMol(temp_val)
'寿命状态
temp_val = databuff(7)
temp_val <<= 8
temp_val += databuff(8)
'Show_Device_Work_Time(temp_val)
'设备时间
temp_val = databuff(9)
temp_val <<= 8
temp_val += databuff(10)
temp_val <<= 8
temp_val += databuff(11)
temp_val <<= 8
temp_val += databuff(12)
'Show_Device_Present_Time(temp_val)
Return &H0
Else
Return &H1
End If
Else
Return &H1
End If
Else
Return &H1
End If
ElseIf databuff(0) = &HAE Then
'设置回复数据
'Select Case databuff(3)
' Case &H1
' 'AppendTipText("设置成功" & vbCrLf, Color.Blue)
' Return &H0
' Case &H2
' Device_Read_Set_Info_Parsing(databuff)
' Return &H0
' Case &H3
' ' Device_Record_Info_Parsing(databuff)
' Return &H0
'End Select
SendNodeDicParsing(databuff)
Else
Return &H1
End If
Return &H1
End Function
'枚举SendNodeDic 设置对应数据
Public isnotSendNode As Boolean = False
Public IsSetTime As Boolean = False
Public IsRtcTime As Boolean = False
Private Sub SendNodeDicParsing(databuff() As Byte)
Dim node As SendNode
Dim nextNode As SendNode
Dim l1, l2 As String
Dim dt As Date
Dim buff() As Byte
Dim ndatabuff(databuff.Length - 1) As Byte
'拷贝数据到新数组
Array.Copy(databuff, 0, ndatabuff, 0, ndatabuff.Length)
For i = 0 To SendNodeDic.Count - 1
node = SendNodeDic(i).Item2
If node.SendStatus = SendNode.SendStatusEnum.Send Then
If node.RecvStatus = SendNode.RecvStatusEnum.None Then
If databuff(3) = 2 Then
If databuff(3) = node.SendData(3) AndAlso databuff(4) = node.SendData(4) Then
node.RecvRefresh(ndatabuff)
If databuff(3) = 2 AndAlso databuff(4) = 2 Then
If databuff(5) = 0 Then
isnotSendNode = True
'IsRuningTest = False
Else
isnotSendNode = False
End If
If i = SendNodeDic.Count - 2 Then
nextNode = SendNodeDic(i - 1).Item2
If nextNode.SendStatus = SendNode.SendStatusEnum.Send AndAlso
nextNode.RecvStatus = SendNode.RecvStatusEnum.Recv AndAlso nextNode.SendData(3) = 1 AndAlso
nextNode.SendData(4) = 8 Then
l1 = CombineFourBytesToLong(nextNode.SendData(8), nextNode.SendData(7), nextNode.SendData(6), nextNode.SendData(5))
buff = node.RecvDataLisr(0)
l2 = CombineFourBytesToLong(buff(61), buff(60), buff(59), buff(58))
If l1.Equals(l2) Then
IsSetTime = False
Else
IsSetTime = True
IsRuningTest = False
End If
End If
End If
End If
If databuff(3) = 2 AndAlso databuff(4) = 1 Then
If i = SendNodeDic.Count - 1 Then
dt = Date.Parse($"20{Hex2(databuff(6))}-{Hex2(databuff(7))}-{Hex2(databuff(8))} {Hex2(databuff(9))}:{Hex2(databuff(10))}:{Hex2(databuff(11))}")
Dim temp_val As Long = (Now - dt).TotalSeconds
'Console.WriteLine($"RTC时间差 {temp_val}")
If RTC_Time.Year = dt.Year AndAlso RTC_Time.Month = dt.Month AndAlso RTC_Time.Day = dt.Day AndAlso
RTC_Time.Hour = dt.Hour AndAlso RTC_Time.Minute = dt.Minute AndAlso RTC_Time.Second = dt.Second Then
IsRtcTime = True
IsRuningTest = False
Else
If temp_val <= Timediffe Then
IsRtcTime = False
Else
IsRtcTime = True
IsRuningTest = False
End If
End If
End If
End If
End If
Else
If databuff(3) = node.SendData(3) Then
'将数组转字符串比对两个数组是否相等
If ByteToString(ndatabuff, node.SendData.Length) = ByteToString(node.SendData, node.SendData.Length) Then
Continue For
End If
node.RecvRefresh(ndatabuff)
End If
End If
End If
End If
Next
End Sub
''' <summary>
''' 显示串口回复数据
''' </summary>
''' <param name="databuff"></param>
Private Sub ShowPortReceData(databuff() As Byte)
Dim portData As String = ByteToString(databuff)
Dim timeData As String
Dim cutTime As String
_nowTime = Now
_timeInterbval = _nowTime - _lastTime
_lastTime = _nowTime
timeData = $"{Math.Round(_timeInterbval.TotalMilliseconds, 0)}"
timeData = timeData.PadRight(6)
cutTime = $"{Now:HH:mm:ss:fff}"
AppendTipText("Com-RX:", Color.Blue)
AppendTipText("(" & cutTime & "-", Color.Black)
AppendTipText(timeData, Color.BlueViolet)
AppendTipText("):", Color.Black)
AppendTipText(portData & vbCrLf, Color.Blue)
End Sub
#End Region
#Region "通讯记录"
''' <summary>
''' 清除记录
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button24_Click(sender As Object, e As EventArgs) Handles Button24.Click
RichTextBox1.Clear()
End Sub
''' <summary>
''' 添加记录文本和颜色
''' </summary>
''' <param name="str">需要添加的记录内容</param>
''' <param name="cor">需要设置的记录颜色</param>
Public Sub AppendTextAndSetStyle(ByVal str As String, ByVal cor As Color)
Dim selStart As Integer
Dim selLength As Integer
selStart = RichTextBox1.TextLength
RichTextBox1.AppendText(str)
selLength = RichTextBox1.TextLength - selStart
RichTextBox1.Select(selStart, selLength)
RichTextBox1.SelectionColor = cor
End Sub
''' <summary>
''' 添加记录
''' </summary>
''' <param name="recordString"></param>
''' <param name="col"></param>
Public Sub AppendTipText(recordString As String, col As Color)
If RichTextBox1.InvokeRequired Then
RichTextBox1.Invoke(New Action(Sub()
If RichTextBox1.Lines.Count >= 256 Then RichTextBox1.Clear()
AppendTextAndSetStyle($"{recordString}", col)
RichTextBox1.ScrollToCaret()
End Sub))
Else
If RichTextBox1.Lines.Count >= 256 Then RichTextBox1.Clear()
AppendTextAndSetStyle($"{recordString}", col)
RichTextBox1.ScrollToCaret()
End If
End Sub
#End Region
#Region "解析串口数据"
''' <summary>
''' 解析串口数据
''' </summary>
''' <param name="databuff"></param>
Private Function AnalyticalData(databuff() As Byte) As Byte
If databuff(0) = &HF0 Then
If databuff(1) = &HF0 Then
If databuff(2) = &HF0 Then
If databuff(3) = &HF0 Then
Dim temp_val As Integer = 0
'产品状态
Show_Device_Work_State(databuff(4))
'浓度状态
temp_val = databuff(5)
temp_val <<= 8
temp_val += databuff(6)
Show_Device_GasMol(temp_val)
'寿命状态
temp_val = databuff(7)
temp_val <<= 8
temp_val += databuff(8)
Show_Device_Work_Time(temp_val)
'设备时间
temp_val = databuff(9)
temp_val <<= 8
temp_val += databuff(10)
temp_val <<= 8
temp_val += databuff(11)
temp_val <<= 8
temp_val += databuff(12)
Show_Device_Present_Time(temp_val)
Return &H0
Else
Return &H1
End If
Else
Return &H1
End If
Else
Return &H1
End If
ElseIf databuff(0) = &HAE Then
'设置回复数据
Select Case databuff(3)
Case &H1
AppendTipText("设置成功" & vbCrLf, Color.Blue)
Return &H0
Case &H2
Device_Read_Set_Info_Parsing(databuff)
Return &H0
Case &H3
Device_Record_Info_Parsing(databuff)
Return &H0
End Select
Else
Return &H1
End If
Return &H1
End Function
''' <summary>
''' Byte数组转字符串
''' </summary>
''' <param name="databuff"></param>
''' <returns></returns>
Public Function ByteToString(databuff() As Byte)
Dim strData As String = String.Empty
For i = 0 To databuff.Length - 1
strData &= $" {Hex(databuff(i)).PadLeft(2, "0"c)}"
Next
Return strData
End Function
Public Function ByteToString(databuff() As Byte, dataLen As Integer)
Dim strData As String = String.Empty
For i = 0 To dataLen - 1
strData &= $" {Hex(databuff(i)).PadLeft(2, "0"c)}"
Next
Return strData
End Function
#End Region
#Region "设置读取信息"
''' <summary>
''' 读取核心参数信息-委托
''' </summary>
Delegate Sub RefreshState_Show(state As Byte)
Delegate Sub RefreshVal_Show(state As Integer)
Delegate Sub RefreBuff_Show(buff() As Byte)
Public Sub Show_Device_Setinfo_Info()
'稳定消抖时间 - 单位s
TextBox6.Text = "30"
'背景值滤波长度 - 最大300S
TextBox13.Text = "300"
'传感器极大值
TextBox7.Text = "3500"
'传感器极小值
TextBox8.Text = "500"
'预热时间 - 单位:分钟
TextBox14.Text = "3"
'LEV 10% 对应的ADC 值
TextBox1.Text = "2800"
'LEV 0% 对应的ADC 值
TextBox2.Text = "1000"
'触发 - 消抖次数
TextBox3.Text = "150"
'释放 - 消抖次数
TextBox4.Text = "150"
'稳定阈值
TextBox5.Text = "30"
'报警点提前量
TextBox11.Text = "100"
'校准超时 - 单位S
TextBox12.Text = "180"
'校准0% LEL 下限
TextBox15.Text = "100"
'校准0% LEL 上限
TextBox16.Text = "2200"
'校准10% LEL 下限
TextBox19.Text = "1000"
'校准10% LEL 上限
TextBox20.Text = "3400"
'校准差值 下限
TextBox17.Text = "1000"
'校准差值 上限
TextBox18.Text = "2500"
'泄露恢复至正常 条件1稳定处于基准值的多少倍以内且达到消抖次数多少秒
TextBox21.Text = "1.2" '基准倍数
TextBox22.Text = "5" '消抖时间
'泄露恢复至正常 条件2稳定处于基准值的多少倍以内且持续时间超过多少分钟
TextBox23.Text = "1.5" '基准倍数
TextBox24.Text = "120" '消抖时间
End Sub
''' <summary>
''' 显示开关状态
''' </summary>
''' <param name="state"></param>
Public Sub Show_Device_Work_State(state As Byte)
If InvokeRequired = True Then
Dim dev As New RefreshState_Show(AddressOf Show_Device_Work_State)
Me.Invoke(dev, New Object() {state})
Else
Select Case state
Case &H2F
Lab_DeviceState.ForeColor = Color.Orange
Lab_DeviceState.Text = "预热"
Case &HB
Lab_DeviceState.ForeColor = Color.Green
Lab_DeviceState.Text = "正常"
Case &H48
Lab_DeviceState.ForeColor = Color.Red
Lab_DeviceState.Text = "报警"
End Select
End If
End Sub
''' <summary>
''' 显示设备浓度
''' </summary>
''' <param name="mol"></param>
Public Sub Show_Device_GasMol(mol As Integer)
If InvokeRequired = True Then
Dim dev As New RefreshVal_Show(AddressOf Show_Device_GasMol)
Me.Invoke(dev, New Object() {mol})
Else
Lab_mol.ForeColor = Color.Black
Lab_mol.Text = mol.ToString & " mV"
End If
End Sub
''' <summary>
''' 显示工作天数
''' </summary>
''' <param name="day"></param>
Public Sub Show_Device_Work_Time(day As Integer)
If InvokeRequired = True Then
Dim dev As New RefreshVal_Show(AddressOf Show_Device_Work_Time)
Me.Invoke(dev, New Object() {day})
Else
Lab_WorkTime.ForeColor = Color.Black
Lab_WorkTime.Text = day.ToString & ""
End If
End Sub
''' <summary>
''' 显示当前时间
''' </summary>
''' <param name="time"></param>
Public Sub Show_Device_Present_Time(time As Integer)
If InvokeRequired = True Then
Dim dev As New RefreshVal_Show(AddressOf Show_Device_Present_Time)
Me.Invoke(dev, New Object() {time})
Else
Dim dateTimeOffset As DateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(time)
Dim localTime As DateTime = dateTimeOffset.LocalDateTime
Lab_DeviceTime.Text = localTime.ToString("yyyy-MM-dd HH:mm:ss")
End If
End Sub
''' <summary>
''' 将 Int32 转为 4 字节数组,低字节在前。
''' </summary>
Public Function IntTo4BytesLE(value As Integer) As Byte()
Return BitConverter.GetBytes(value) ' BitConverter 在 Windows/Intel 就是 Little-Endian
End Function
''' <summary>
''' Int转2个字节Byte
''' 高字节在前,低字节在后
''' </summary>
''' <param name="i"></param>
''' <returns></returns>
Public Function IntToByteHB(ByVal i As Integer) As Byte()
Dim btemp() As Byte = {0, 0}
Dim b() As Byte = BitConverter.GetBytes(i)
btemp(0) = b(0)
btemp(1) = b(1)
Return btemp
End Function
''' <summary>
''' 和校验取余数
''' 求Byte数组的和校验取余数
''' </summary>
''' <param name="dataPacket">Byte数组</param>
''' <returns></returns>
Public Function GetSumCheckMod(dataPacket As Byte()) As Byte
Dim sum As Integer
For idx = 0 To dataPacket.Length - 1
sum += dataPacket(idx)
sum = sum And &HFF
Next
Dim sumMod As Byte = &HFF - sum
Return sumMod
End Function
Public Function GetSumCheckMod(dataPacket As Byte(), dataLen As Integer) As Byte
Dim sum As Integer
For idx = 0 To dataLen - 1
sum += dataPacket(idx)
sum = sum And &HFF
Next
Dim sumMod As Byte = &HFF - sum
Return sumMod
End Function
Public Sub Show_Device_ReadRtc(buff() As Byte)
If InvokeRequired = True Then
Dim dev As New RefreBuff_Show(AddressOf Show_Device_ReadRtc)
Me.Invoke(dev, New Object() {buff})
Else
DateTimePicker1.Value = New DateTime(CInt($"20{Hex(buff(6))}"), CInt($"{Hex(buff(7))}"), CInt($"{Hex(buff(8))}"), CInt($"{Hex(buff(9))}"), CInt($"{Hex(buff(10))}"), CInt($"{Hex(buff(11))}"))
End If
End Sub
Public Function ConvertUtcTimestampToDateTime(timestamp As Long) As DateTime
' 创建一个 DateTime 对象,表示从 Unix 时间戳转换而来的时间
Dim unixEpoch As New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
' 添加时间戳所表示的秒数
Dim convertedDateTime As DateTime = unixEpoch.AddSeconds(timestamp)
' 返回本地时间
Return convertedDateTime.ToLocalTime()
End Function
Public Sub Show_Device_SetInfo(buff() As Byte)
If InvokeRequired = True Then
Dim dev As New RefreBuff_Show(AddressOf Show_Device_SetInfo)
Me.Invoke(dev, New Object() {buff})
Else
Dim temp_val As Integer
Dim temp_len As Integer = 6
'稳定消抖时间 - 单位s
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox6.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'背景值滤波长度 - 最大600S
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox13.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'传感器极大值
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox7.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'传感器极小值
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox8.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'预热时间 - 单位:分钟
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox14.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'LEV 10% 对应的ADC 值
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox1.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'LEV 0% 对应的ADC 值
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox2.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'触发 - 消抖次数
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox3.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'释放 - 消抖次数
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox4.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'稳定阈值
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox5.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'报警点提前量
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox11.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'校准超时 - 单位S
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox12.Text = temp_val.ToString
AppendTipText($"报警电压 {temp_val}" & vbCrLf, Color.Blue)
'校准0% LEL 下限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox15.Text = temp_val.ToString
AppendTipText($"校准0% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'校准0% LEL 上限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox16.Text = temp_val.ToString
AppendTipText($"校准0% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'校准10% LEL 下限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox19.Text = temp_val.ToString
AppendTipText($"校准10% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'校准10% LEL 上限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox20.Text = temp_val.ToString
AppendTipText($"校准10% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'校准差值 下限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox17.Text = temp_val.ToString
AppendTipText($"校准0% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'校准差值 上限
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox18.Text = temp_val.ToString
AppendTipText($"校准0% LEL 下限 {temp_val}" & vbCrLf, Color.Blue)
'泄露条件1 - 基准值的倍数
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
Dim temp_mult As Double = temp_val / 10
TextBox21.Text = temp_mult.ToString
AppendTipText($"泄露条件1 - 基准值的 {temp_mult}倍数" & vbCrLf, Color.Blue)
'泄露条件1 - 消抖时间
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox22.Text = temp_val.ToString
AppendTipText($"泄露条件1 - 消抖时间: {temp_val}S" & vbCrLf, Color.Blue)
'泄露条件2 - 基准值的倍数
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
temp_mult = temp_val / 10
TextBox23.Text = temp_mult.ToString
AppendTipText($"泄露条件2 - 基准值的 {temp_mult}倍数" & vbCrLf, Color.Blue)
'泄露条件2 - 消抖时间
temp_val = buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
temp_len += 2
TextBox24.Text = temp_val.ToString
AppendTipText($"泄露条件2 - 消抖时间: {temp_val}Min" & vbCrLf, Color.Blue)
'生产时间戳
temp_val = buff(temp_len + 3)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len + 2)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len + 1)
temp_val <<= 8
temp_val = temp_val Or buff(temp_len)
DateTimeP_RelDate.Value = ConvertUtcTimestampToDateTime(temp_val)
AppendTipText($"生产时间 " & DateTimeP_RelDate.Value & vbCrLf, Color.Blue)
End If
End Sub
Public Sub Device_Read_Set_Info_Parsing(buff As Byte())
Select Case buff(4)
Case &H1
If buff(5) = &H0 Then
AppendTipText("读取RTC时间成功" & vbCrLf, Color.Blue)
AppendTipText($"RTC: 20{Hex(buff(6))}-{Hex(buff(7))}-{Hex(buff(8))} {Hex(buff(9))}:{Hex(buff(10))}:{Hex(buff(11))} {Hex(buff(12))} " & vbCrLf, Color.Blue)
Show_Device_ReadRtc(buff)
Else
AppendTipText("读取RTC时间失败" & vbCrLf, Color.Red)
End If
Case &H2
If buff(5) = &H0 Then
AppendTipText("读取 设置参数 成功" & vbCrLf, Color.Blue)
Show_Device_SetInfo(buff)
Else
AppendTipText("读取 设置参数 失败" & vbCrLf, Color.Blue)
End If
End Select
End Sub
Public Sub Device_LogInfo_Data_Parsing(data As Integer)
If InvokeRequired = True Then
Dim dev As New RefreshVal_Show(AddressOf Device_LogInfo_Data_Parsing)
Me.Invoke(dev, New Object() {data})
Else
TextBox9.Text = data.ToString()
End If
End Sub
Public Sub Device_Log_Data_Parsing(buff As Byte())
If InvokeRequired = True Then
Dim dev As New RefreBuff_Show(AddressOf Device_Log_Data_Parsing)
Me.Invoke(dev, New Object() {buff})
Else
If buff(0) = &H1A And buff(2) = &HE Then
If GetSumCheckMod(buff, &HE) = &H0 Then
Dim temp_rtc_tick As Integer
Dim temp_val As Integer
Dim log_temp_data As New LOG_Data_List
log_temp_data.sn = buff(1)
temp_rtc_tick = buff(4)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(5)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(6)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(7)
log_temp_data.time = ConvertUtcTimestampToDateTime(temp_rtc_tick)
AppendTipText($"LOG " & log_temp_data.time & vbCrLf, Color.Blue)
log_temp_data.type = buff(8)
Select Case buff(8)
Case &H1
AppendTipText($"记录类型 - 浓度报警记录" & vbCrLf, Color.Blue)
temp_rtc_tick = buff(9)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(10)
log_temp_data.parsing = $"浓度报警 {temp_rtc_tick} {buff(12)}% {buff(11)}℃"
Case &H2
AppendTipText($"记录类型 - 浓度恢复记录" & vbCrLf, Color.Blue)
temp_rtc_tick = buff(9)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(10)
log_temp_data.parsing = $"浓度恢复 {temp_rtc_tick} {buff(12)}% {buff(11)}℃"
Case &H3
AppendTipText($"记录类型 - 产品故障记录" & vbCrLf, Color.Blue)
log_temp_data.parsing = $"产品故障 {buff(9)} {buff(11)}℃"
Case &H4
AppendTipText($"记录类型 - 产品故障恢复记录" & vbCrLf, Color.Blue)
log_temp_data.parsing = $"产品故障恢复 {buff(9)} {buff(11)}℃"
Case &H5
AppendTipText($"记录类型 - 产品上电记录" & vbCrLf, Color.Blue)
log_temp_data.parsing = $"产品上电 "
Case &H6
AppendTipText($"记录类型 - 产品断电记录" & vbCrLf, Color.Blue)
log_temp_data.parsing = $"产品断电 "
Case &H7
AppendTipText($"记录类型 - 传感器失效记录" & vbCrLf, Color.Blue)
log_temp_data.parsing = $"传感器失效 "
Case &H8
AppendTipText($"记录类型 - 传感器校准记录" & vbCrLf, Color.Blue)
temp_rtc_tick = buff(9)
temp_rtc_tick <<= 8
temp_rtc_tick = temp_rtc_tick Or buff(10)
temp_val = buff(11)
temp_val <<= 8
temp_val = temp_val Or buff(12)
log_temp_data.parsing = $"传感器校准 LEL_0:{temp_rtc_tick} LEL_10:{temp_val}"
End Select
'将解析后的数据添加到列表中
Dim log_sn As Integer = CInt(TextBox10.Text)
'Console.WriteLine($"Log sn:{log_sn} - {Log_Data.Count}")
If Log_Data.Count > log_sn Then
Log_Data(log_sn) = log_temp_data
Grid_Refresh_LOG_Data(Log_Data, log_sn + 1, Grid1)
'Console.WriteLine($"Refresh_LOG_Data ")
Else
Log_Data.Add(log_temp_data)
Grid_ADD_LOG_Data(Log_Data, Grid1)
'Console.WriteLine($"Add new line ")
End If
End If
End If
End If
End Sub
Public Sub Device_Record_Info_Parsing(buff As Byte())
Select Case buff(4)
Case &H0
If buff(5) = &H0 Then
AppendTipText("读取成功" & vbCrLf, Color.Blue)
Dim Log_num As Integer
Dim log_addr As Integer
Log_num = buff(6)
Log_num <<= 8
Log_num += buff(7)
log_addr = buff(8)
log_addr <<= 8
log_addr += buff(9)
log_addr <<= 8
log_addr += buff(10)
log_addr <<= 8
log_addr += buff(11)
AppendTipText($"日志数量:{Log_num} 日志地址:{Hex(log_addr)}" & vbCrLf, Color.Blue)
Device_LogInfo_Data_Parsing(Log_num)
Else
AppendTipText("读取失败" & vbCrLf, Color.Blue)
End If
Case &H1
If buff(5) = &H0 Then
AppendTipText("读取日志成功" & vbCrLf, Color.Blue)
Dim log_data(100) As Byte
Dim log_len As Byte = buff(1) - 7
Array.Copy(buff, 6, log_data, 0, log_len)
AppendTipText("读取日志数据 " & ByteToString(log_data, log_len) & vbCrLf, Color.Blue)
Device_Log_Data_Parsing(log_data)
Else
AppendTipText("读取日志失败" & vbCrLf, Color.Blue)
End If
End Select
End Sub
Private Sub But_SetRTCTime_Click(sender As Object, e As EventArgs) Handles But_SetRTCTime.Click
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 13 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H1 '参数内容 - 设置RTC时间
If CheckBox2.Checked = True Then
'使用系统时间
send_data(5) = $"&H{Now.Date.Year Mod 100}"
send_data(6) = $"&H{Now.Date.Month Mod 100}"
send_data(7) = $"&H{Now.Date.Day Mod 100}"
send_data(8) = $"&H{Now.Hour}"
send_data(9) = $"&H{Now.Minute }"
send_data(10) = $"&H{Now.Second }"
send_data(11) = $"&H{Now.Date.DayOfWeek Mod 100}"
Else
'自定义时间
send_data(5) = $"&H{DateTimePicker1.Value.Year Mod 100}"
send_data(6) = $"&H{DateTimePicker1.Value.Month Mod 100}"
send_data(7) = $"&H{DateTimePicker1.Value.Day Mod 100}"
send_data(8) = $"&H{DateTimePicker1.Value.Hour}"
send_data(9) = $"&H{DateTimePicker1.Value.Minute }"
send_data(10) = $"&H{DateTimePicker1.Value.Second }"
send_data(11) = $"&H{DateTimePicker1.Value.DayOfWeek Mod 100}"
End If
send_data(12) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 13)
SendPortData(send_data, 13)
End Sub
Public Function GetSetRTCTime() As Byte()
Dim send_data(12) As Byte
send_data(0) = &HAE '包头
send_data(1) = 13 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H1 '参数内容 - 设置RTC时间
RTC_Time = Now
If CheckBox2.Checked = True Then
'使用系统时间
send_data(5) = $"&H{RTC_Time.Date.Year Mod 100}"
send_data(6) = $"&H{RTC_Time.Date.Month Mod 100}"
send_data(7) = $"&H{RTC_Time.Date.Day Mod 100}"
send_data(8) = $"&H{RTC_Time.Hour}"
send_data(9) = $"&H{RTC_Time.Minute }"
send_data(10) = $"&H{RTC_Time.Second }"
send_data(11) = $"&H{RTC_Time.Date.DayOfWeek Mod 100}"
Else
'自定义时间
send_data(5) = $"&H{DateTimePicker1.Value.Year Mod 100}"
send_data(6) = $"&H{DateTimePicker1.Value.Month Mod 100}"
send_data(7) = $"&H{DateTimePicker1.Value.Day Mod 100}"
send_data(8) = $"&H{DateTimePicker1.Value.Hour}"
send_data(9) = $"&H{DateTimePicker1.Value.Minute }"
send_data(10) = $"&H{DateTimePicker1.Value.Second }"
send_data(11) = $"&H{DateTimePicker1.Value.DayOfWeek Mod 100}"
End If
send_data(12) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 13)
Return send_data
End Function
Public Function GetSetUTCTime() As Byte()
Dim send_data(9) As Byte
send_data(0) = &HAE '包头
send_data(1) = 10 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H8 '参数内容 - 设置RTC时间
'获取到秒的UTC时间戳
Dim Utc As Integer = CInt((DateTime.Now - New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds)
'将UTC时间戳转换为字节数组
Dim UtcBytes As Byte() = BitConverter.GetBytes(Utc)
send_data(5) = UtcBytes(0)
send_data(6) = UtcBytes(1)
send_data(7) = UtcBytes(2)
send_data(8) = UtcBytes(3)
send_data(9) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 10)
Return send_data
End Function
Private Sub But_ReleaseDate_Click(sender As Object, e As EventArgs) Handles But_ReleaseDate.Click
Dim send_data(100) As Byte
Dim temp_len As Integer = 0
send_data(0) = &HAE '包头
send_data(1) = 29 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H2 '参数内容 - 设置出厂时间及参数信息
temp_len += 5
Dim unixEpoch As New DateTime(1970, 1, 1, 8, 0, 0, DateTimeKind.Utc)
Dim utcTime As Integer
Dim temp_buff() As Byte
'稳定消抖时间 - 单位:S
temp_buff = BitConverter.GetBytes(CInt(TextBox6.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'背景值滤波长度 - 最大600S
temp_buff = BitConverter.GetBytes(CInt(TextBox13.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'传感器极大值 - 最大4095
temp_buff = BitConverter.GetBytes(CInt(TextBox7.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'传感器极小值 - 最大3000
temp_buff = BitConverter.GetBytes(CInt(TextBox8.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'预热时间 - 单位:分钟
temp_buff = BitConverter.GetBytes(CInt(TextBox14.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'LEV 10% 对应的ADC 值
temp_buff = BitConverter.GetBytes(CInt(TextBox1.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'LEV 0% 对应的ADC 值
temp_buff = BitConverter.GetBytes(CInt(TextBox2.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'触发 - 消抖次数
temp_buff = BitConverter.GetBytes(CInt(TextBox3.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'释放 - 消抖次数
temp_buff = BitConverter.GetBytes(CInt(TextBox4.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'稳定阈值
temp_buff = BitConverter.GetBytes(CInt(TextBox5.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'报警点提前量
temp_buff = BitConverter.GetBytes(CInt(TextBox11.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准超时 - 单位S
temp_buff = BitConverter.GetBytes(CInt(TextBox12.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准0% LEL下限 -
temp_buff = BitConverter.GetBytes(CInt(TextBox15.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准0% LEL上限 -
temp_buff = BitConverter.GetBytes(CInt(TextBox16.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准10% LEL下限 -
temp_buff = BitConverter.GetBytes(CInt(TextBox19.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准10% LEL上限 -
temp_buff = BitConverter.GetBytes(CInt(TextBox20.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准差值下限
temp_buff = BitConverter.GetBytes(CInt(TextBox17.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'校准差值上限
temp_buff = BitConverter.GetBytes(CInt(TextBox18.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'恢复正常模式条件1基准倍数 扩大10倍进行数据下发
Dim temp_mult As Integer = (CDbl(TextBox21.Text) * 10)
temp_buff = BitConverter.GetBytes(temp_mult)
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'恢复正常模式条件1消抖时间
temp_buff = BitConverter.GetBytes(CInt(TextBox22.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'恢复正常模式条件2基准倍数 扩大10倍进行数据下发
temp_mult = (CDbl(TextBox23.Text) * 10)
temp_buff = BitConverter.GetBytes(temp_mult)
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'恢复正常模式条件2消抖时间
temp_buff = BitConverter.GetBytes(CInt(TextBox24.Text))
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
'设备出厂时间
utcTime = CInt((DateTimeP_RelDate.Value - unixEpoch).TotalSeconds)
'Console.WriteLine("DateTimeP_RelDate UTC时间: " & utcTime)
temp_buff = BitConverter.GetBytes(utcTime)
send_data(temp_len) = temp_buff(0)
temp_len += 1
send_data(temp_len) = temp_buff(1)
temp_len += 1
send_data(temp_len) = temp_buff(2)
temp_len += 1
send_data(temp_len) = temp_buff(3)
temp_len += 1
send_data(temp_len) = &HEA '包尾
temp_len += 1
send_data(1) = temp_len '长度
send_data(2) = GetSumCheckMod(send_data, temp_len)
SendPortData(send_data, temp_len)
End Sub
Public Function Judge_Volt_Range(sender As Object, e As EventArgs) As Byte
Dim rev As Byte
Dim temp_obj As TextBox = sender
If temp_obj.TextLength > 0 AndAlso CUInt(temp_obj.Text) > 4096 Then
temp_obj.Text = 4095
MsgBox($"超出范围:{CUInt(temp_obj.Text)} 输入范围0~4095")
ElseIf temp_obj.TextLength = 0 Then
temp_obj.Text = 0
End If
Return rev
End Function
Public Function Judge_Debounce_Range(sender As Object, e As EventArgs) As Byte
Dim rev As Byte
Dim temp_obj As TextBox = sender
If temp_obj.TextLength > 0 AndAlso CUInt(temp_obj.Text) > 5000 Then
temp_obj.Text = 4999
MsgBox($"超出范围:{CUInt(temp_obj.Text)} 输入范围0~4999")
ElseIf temp_obj.TextLength = 0 Then
temp_obj.Text = 0
End If
Return rev
End Function
Private Sub TBox_Volt_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged, TextBox5.TextChanged, TextBox2.TextChanged, TextBox11.TextChanged, TextBox13.TextChanged, TextBox12.TextChanged, TextBox7.TextChanged, TextBox20.TextChanged, TextBox19.TextChanged, TextBox18.TextChanged, TextBox17.TextChanged, TextBox16.TextChanged, TextBox15.TextChanged, TextBox21.TextChanged, TextBox24.TextChanged, TextBox23.TextChanged, TextBox22.TextChanged
Judge_Volt_Range(sender, e)
End Sub
Private Sub TBox_Debounce_TextChanged(sender As Object, e As EventArgs) Handles TextBox3.TextChanged, TextBox6.TextChanged, TextBox4.TextChanged, TextBox8.TextChanged, TextBox14.TextChanged
Judge_Debounce_Range(sender, e)
End Sub
Private Sub But_QueryLogInfo_Click(sender As Object, e As EventArgs) Handles But_QueryLogInfo.Click
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H3 '命令 - 读取日志信息
send_data(4) = &H0 '参数内容 -
send_data(5) = &H0
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked = True Then
CheckBox2.Checked = False
Else
CheckBox2.Checked = True
End If
End Sub
Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
If CheckBox2.Checked = True Then
CheckBox1.Checked = False
Else
CheckBox1.Checked = True
End If
End Sub
''' <summary>
''' 定期上报开关
''' </summary>
Dim periodic_reporting_switch As Byte
''' <summary>
''' 开启定时上报
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim send_data(20) As Byte
If periodic_reporting_switch = &H1 Then
periodic_reporting_switch = &H0
Else
periodic_reporting_switch = &H1
End If
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 读取日志信息
send_data(4) = &H4 '参数内容 -
send_data(5) = periodic_reporting_switch
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
If SendPortData(send_data, 8) = True Then
If periodic_reporting_switch = &H1 Then
Button2.Text = "关闭上报"
Button2.ForeColor = Color.Red
Else
Button2.Text = "开启上报"
Button2.ForeColor = Color.Black
End If
End If
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H2 '命令 - 读取日志信息
send_data(4) = &H1 '参数内容 -
send_data(5) = &H0
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' 4、读取校准信息
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H2 '命令 - 读取日志信息
send_data(4) = &H2 '参数内容 -
send_data(5) = &H0
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
'' 读取软件版本号 UUID
'Dim send_data(20) As Byte
'send_data(0) = &HAE '包头
'send_data(1) = 8 '长度
'send_data(2) = &H0 '校验
'send_data(3) = &H2 '命令 - 读取软件版本号
'send_data(4) = &H3 '参数内容 -
'send_data(5) = &H0
'send_data(6) = &H0
'send_data(7) = &HEA '包尾
'send_data(2) = GetSumCheckMod(send_data, 8)
'SendPortData(send_data, 8)
' 5、读取实时状态信息
'Dim send_data(20) As Byte
'send_data(0) = &HAE '包头
'send_data(1) = 8 '长度
'send_data(2) = &H0 '校验
'send_data(3) = &H2 '命令 - 读取实时状态信息
'send_data(4) = &H4 '参数内容 -
'send_data(5) = &H0
'send_data(6) = &H0
'send_data(7) = &HEA '包尾
'send_data(2) = GetSumCheckMod(send_data, 8)
'SendPortData(send_data, 8)
End Sub
''' <summary>
''' 调试信息输出开关
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H6 '参数内容 - 设置调试信息状态
If CheckBox3.Checked = True Then
send_data(5) = &HFF '开启调试信息
Else
send_data(5) = &H0 '关闭调试信息
End If
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
Private Sub CheckBox4_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox4.CheckedChanged
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H5 '参数内容 - 设置调试信息状态
If CheckBox4.Checked = True Then
send_data(5) = &H1 '开启调试曲线信息
Else
send_data(5) = &H0 '关闭调试曲线信息
End If
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
''' <summary>
''' 复位命令下发
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click
Dim send_data(20) As Byte
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H1 '命令 - 设置参数
send_data(4) = &H7 '参数内容 - 复位
send_data(5) = &H1 '关闭调试信息
send_data(6) = &H0
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
''' <summary>
''' 指定查询日志内容
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim send_data(20) As Byte
Dim temp_buff() As Byte = BitConverter.GetBytes(CInt(TextBox10.Text))
send_data(0) = &HAE '包头
send_data(1) = 8 '长度
send_data(2) = &H0 '校验
send_data(3) = &H3 '命令 - 读取日志信息
send_data(4) = &H1 '参数内容 -
send_data(5) = temp_buff(1)
send_data(6) = temp_buff(0)
send_data(7) = &HEA '包尾
send_data(2) = GetSumCheckMod(send_data, 8)
SendPortData(send_data, 8)
End Sub
Dim g_Auto_Log_Query_Enable As Boolean = False
Dim g_Auto_Log_Query_Cnt As Integer = 0
Dim g_Auto_Log_Query_WriteCnt As Integer = 0
Dim g_Auto_Log_Query_ReplyRev As Integer = 0
''' <summary>
''' 一键查询日志内容
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
If g_Auto_Log_Query_Enable Then
'当前处于正在查询日志,停止查询
Timer1.Interval = 10
Timer1.Enabled = False
g_Auto_Log_Query_Cnt = 0
g_Auto_Log_Query_Enable = False
Button6.ForeColor = Color.Black
Button6.Text = "一键查询"
Else
'开启自动查询日志
Timer1.Interval = 10
Timer1.Enabled = True
g_Auto_Log_Query_Cnt = 0
g_Auto_Log_Query_Enable = True
TextBox10.Text = 0
Button6.ForeColor = Color.Red
Button6.Text = "停止查询"
End If
End Sub
''' <summary>
'''
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
g_Auto_Log_Query_Cnt += 1
If g_Auto_Log_Query_Cnt >= 10 Then
g_Auto_Log_Query_Cnt = 0
'TextBox10.Text += 1
Dim temp_num As Integer = CInt(TextBox10.Text)
Dim temp_sum As Integer = CInt(TextBox9.Text)
If SerialPort.IsOpen Then
temp_num += 1
TextBox10.Text = temp_num
Button5.PerformClick()
If temp_num >= temp_sum Then
'查询结束
Timer1.Interval = 10
Timer1.Enabled = False
g_Auto_Log_Query_Cnt = 0
g_Auto_Log_Query_Enable = False
Button6.ForeColor = Color.Black
Button6.Text = "一键查询"
End If
Else
'当前处于正在查询日志,停止查询
Timer1.Interval = 10
Timer1.Enabled = False
g_Auto_Log_Query_Cnt = 0
g_Auto_Log_Query_Enable = False
Button6.ForeColor = Color.Black
Button6.Text = "一键查询"
MsgBox("请打开串口!")
End If
End If
'Console.WriteLine($"Timer1_Tick {g_Auto_Log_Query_Cnt}")
End Sub
''' <summary>
''' 数据时间结构
''' </summary>
Class LOG_DATE
Public year As Int32
Public month As Int32
Public day As Int32
Public hour As Int32
Public minute As Int32
Public second As Int32
Public milliscond As Int32
End Class
Class LOG_Data_List
Public original_data() As Byte
Public sn As Byte
Public time As DateTime
Public type As Byte
Public para_data() As Byte
Public parsing As String
End Class
''' <summary>
''' 解析表格排序
''' </summary>
Enum form_grid1
sn
data_date
data_parsing
End Enum
Dim Log_Data As New List(Of LOG_Data_List)
Private Sub Grid_Format_initial()
'新表格控件
With Grid1
.AutoRedraw = False '禁止刷
.Rows = 6 '返回或设置表格的行数
.Cols = 4
.DefaultFont = New Font("Tahoma", 8) '设置字体
.ExtendLastCol = True '设置扩展最后一列的列宽,让表格可以充满控件
.BackColor1 = Color.FromArgb(231, 235, 247)
.GridColor = Color.FromArgb(148, 190, 231)
.Cell(0, 1).Text = " 序号 "
.Cell(0, 2).Text = " 时间 "
.Cell(0, 3).Text = "内容"
.Column(1).CellType = FlexCell.CellTypeEnum.TextBox
.Column(2).CellType = FlexCell.CellTypeEnum.TextBox
.Column(3).CellType = FlexCell.CellTypeEnum.TextBox
.Column(1).AutoFit()
.Column(2).AutoFit()
.Column(3).AutoFit()
.Column(1).Alignment = FlexCell.AlignmentEnum.CenterCenter
.Column(2).Alignment = FlexCell.AlignmentEnum.CenterCenter '居中对齐
'.Column(3).Alignment = FlexCell.AlignmentEnum.LeftCenter '左对齐
.Column(3).Alignment = FlexCell.AlignmentEnum.CenterCenter '居中对齐
.SelectionMode = FlexCell.SelectionModeEnum.ByRow '整行选取
.DisplayRowNumber = True '开启行号
.AutoRedraw = True
.Refresh() '加载数据
End With
End Sub
''' <summary>
''' 将数据显示到表格中
''' </summary>
''' <param name="data_list"></param>
Public Sub Grid_ADD_LOG_Data(data_list As List(Of LOG_Data_List), show_grid As FlexCell.Grid)
Dim temp_num As Int32
Dim temp_string As String
'将数据对应的序号填充到对应的行号中
If data_list.Count > show_grid.Rows - 1 Then
'Console.WriteLine("Grid - 添加新行")
show_grid.AddItem(" ", True) '添加新行
End If
temp_num = data_list.Count - 1 '获取当前数据列表中有多少条数据
temp_string = $"List Count:{temp_num} Rows:{show_grid.Rows}"
'Console.WriteLine(temp_string)
'show_grid.AddItem(" ", True) '添加新行
show_grid.Cell(data_list.Count, form_grid1.sn + 1).Text = data_list(temp_num).sn
show_grid.Cell(data_list.Count, form_grid1.data_date + 1).Text = data_list(temp_num).time
show_grid.Cell(data_list.Count, form_grid1.data_parsing + 1).Text = data_list(temp_num).parsing
End Sub
Public Sub Grid_Refresh_LOG_Data(data_list As List(Of LOG_Data_List), row As Integer, show_grid As FlexCell.Grid)
Dim temp_num As Int32
Dim temp_string As String
'将数据对应的序号填充到对应的行号中
If row > show_grid.Rows - 1 Then
'Console.WriteLine("Grid - 添加新行")
show_grid.AddItem(" ", True) '添加新行
End If
temp_num = row - 1 '获取当前数据列表中有多少条数据
temp_string = $"List Count:{temp_num} Rows:{show_grid.Rows}"
'Console.WriteLine(temp_string)
show_grid.Cell(row, form_grid1.sn + 1).Text = data_list(temp_num).sn
show_grid.Cell(row, form_grid1.data_date + 1).Text = data_list(temp_num).time
show_grid.Cell(row, form_grid1.data_parsing + 1).Text = data_list(temp_num).parsing
End Sub
Public TextBox2check As Boolean
Private Sub ToolStripTextBox2_TextChanged(sender As Object, e As EventArgs) Handles ToolStripTextBox2.TextChanged
TextBox2check = True
If String.IsNullOrEmpty(ToolStripTextBox2.Text.Trim) Then
TextBox2check = False
End If
Dim str As String
For i = 0 To ToolStripTextBox2.Text.Length - 1
str = ToolStripTextBox2.Text.Substring(i, 1)
'判断 第i个字符 是否在 0到9 A到F 和空格
If Not ((str >= "0" And str <= "9") OrElse
(str.ToUpper >= "A" And str.ToUpper <= "F") OrElse
(str.Equals(" "))) Then
ToolStripTextBox2.ForeColor = Color.Red
TextBox2check = False
''Console.WriteLine($"【{str}】:{ (str >= "0" And str <= "9") }")
''Console.WriteLine($"【{str}】:{ (str.ToUpper >= "A" And str.ToUpper <= "F") }")
''Console.WriteLine($"【{str}】:{ str.Equals(" ")}")
Else
ToolStripTextBox2.ForeColor = Color.Black
End If
Next
End Sub
Public CommandSetDic As Dictionary(Of String, Byte())
Public Sub InitCommandSetDic()
Dim str As String = ProcessTable.Cell(0, 0).Tag
If String.IsNullOrEmpty(str) OrElse str.Length = 0 Then
CommandSetDic = New Dictionary(Of String, Byte())
CommandSetDic.Add("开启上报", HexStringToByteArray("AE 08 59 01 04 01 00 EA"))
CommandSetDic.Add("关闭上报", HexStringToByteArray("AE 08 5A 01 04 00 00 EA"))
CommandSetDic.Add("读取RTC时间", HexStringToByteArray("AE 08 5C 02 01 00 00 EA"))
CommandSetDic.Add("设置RTC时间", {})
CommandSetDic.Add("设置生产时间", {})
CommandSetDic.Add("延时", {2})
CommandSetDic.Add("获取服务器key", {0})
CommandSetDic.Add("设置设备key", {0})
CommandSetDic.Add("读取设备key", {"AE 08 54 02 09 00 00 EA"})
Else
CommandSetDic = JsonConvert.DeserializeObject(Of Dictionary(Of String, Byte()))(str)
End If
SendNodeDic = New List(Of (String, SendNode))
End Sub
Public FileCPatrh = $"{Application.StartupPath}\NT318"
Public Sub SaveCommandSetDic()
ProcessTable.Cell(0, 0).Tag = JsonConvert.SerializeObject(CommandSetDic)
If Not IO.Directory.Exists(FileCPatrh & "\CommandSetDic") Then
IO.Directory.CreateDirectory(FileCPatrh & "\CommandSetDic")
End If
ProcessTable.SaveFile(FileCPatrh & "\CommandSetDic.flx")
'判断日文件夹在不在
If Not IO.Directory.Exists(FileCPatrh & "\Log") Then
IO.Directory.CreateDirectory(FileCPatrh & "\Log")
End If
Grid_table.SaveFile(FileCPatrh & $"\Log\{Now.ToString("yyyyMMddHHmmss")}.flx")
End Sub
Public Sub InitLoadProcessTable(Optional isFile As Boolean = True)
If isFile Then
If IO.File.Exists(FileCPatrh & "\CommandSetDic.flx") Then
ProcessTable.OpenFile(FileCPatrh & "\CommandSetDic.flx")
Return
End If
End If
ProcessTable.NewFile()
ProcessTable.Cols = 5
ProcessTable.Rows = 1
ProcessTable.DisplayRowNumber = True
ProcessTable.ExtendLastCol = True
ProcessTable.Cell(0, 0).Text = "序号"
ProcessTable.Cell(0, 1).Text = "勾选"
ProcessTable.Cell(0, 2).Text = "命令别名"
ProcessTable.Cell(0, 3).Text = "命令"
ProcessTable.Cell(0, 4).Text = "发送状态"
ProcessTable.Column(0).Width = 50
ProcessTable.Column(1).Width = 20
ProcessTable.Column(2).Width = 120
ProcessTable.Column(3).Width = 200
ProcessTable.Column(4).Width = 100
ProcessTable.Column(0).Alignment = AlignmentEnum.GeneralCenter
ProcessTable.Column(1).Alignment = AlignmentEnum.GeneralCenter
ProcessTable.Column(2).Alignment = AlignmentEnum.GeneralCenter
ProcessTable.Column(3).Alignment = AlignmentEnum.GeneralCenter
ProcessTable.Column(4).Alignment = AlignmentEnum.GeneralCenter
ProcessTable.Column(1).CellType = CellTypeEnum.CheckBox
ProcessTable.Column(2).CellType = CellTypeEnum.ComboBox
ProcessTable.Column(3).Locked = True
End Sub
Public Sub InitGrid_table()
With Grid_table
.NewFile()
.Rows = 1
.Cols = TableEnum.MAX
.DisplayRowNumber = True
.ExtendLastCol = True
For i = 0 To TableEnum.MAX - 1
If i = 0 Then
.Column(0).Width = 50
End If
.Cell(0, i).Text = GetTableEnumName(i)
.Column(i).Alignment = AlignmentEnum.GeneralCenter
.Column(i).Locked = True
Next
End With
End Sub
Private Sub ToolStripButton1_Click(sender As Object, e As EventArgs) Handles ToolStripButton1.Click
If String.IsNullOrEmpty(T_CommandAlias.Text.Trim) Then
MsgBox("请输入命令别名")
Return
End If
If String.IsNullOrEmpty(ToolStripTextBox2.Text.Trim) Then
MsgBox("请输入命令")
Return
End If
Dim CommandAlia As String = T_CommandAlias.Text.Trim
Dim Command As String = ToolStripTextBox2.Text.Trim
If CommandSetDic.ContainsKey(CommandAlia) Then
'提示框提示用户是否需要覆盖
If MsgBox("该命令别名已存在,是否覆盖?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
CommandSetDic(CommandAlia) = HexStringToByteArray(Command)
End If
Else
CommandSetDic.Add(CommandAlia, HexStringToByteArray(Command))
End If
End Sub
''' <summary>
''' 将字符串按 UTF-8 编码转成 Byte 数组。
''' </summary>
Public Function StringToBytes(ByVal s As String) As Byte()
Return System.Text.Encoding.UTF8.GetBytes(s)
End Function
'将16进制字符串转换为字节数组
Private Function HexStringToByteArray(hex As String) As Byte()
Dim bytes As New List(Of Byte)
hex = hex.Replace(" ", "").Trim.ToUpper()
For i As Integer = 0 To hex.Length - 1 Step 2
Dim hexByte As String = hex.Substring(i, 2)
bytes.Add(Convert.ToByte(hexByte, 16))
Next
Return bytes.ToArray()
End Function
'将字节数组转换为16进制字符串
Private Function ByteArrayToHexString(bytes As Byte()) As String
If bytes Is Nothing OrElse bytes.Length = 0 Then Return ""
Dim hex As String = ""
For Each b As Byte In bytes
hex += b.ToString("X2") & " "
Next
Return hex.Trim()
End Function
Private Sub ProcessTable_ComboDropDown(Sender As Object, e As Grid.ComboDropDownEventArgs) Handles ProcessTable.ComboDropDown
If e.Row = 0 Then Return
If e.Col = 2 Then
ProcessTable.ComboBox(e.Col).Items.Clear()
ProcessTable.ComboBox(e.Col).Items.AddRange(CommandSetDic.Keys.ToArray())
End If
End Sub
Public SendNodeDic As List(Of (String, SendNode))
Public StartSendThread As Thread
Public IsRuningTest As Boolean = False
Public IsStopTest As Boolean = False
Private Sub ToolStripButton3_Click(sender As Object, e As EventArgs) Handles ToolStripButton3.Click
If ToolStripButton3.Text = "开始校时" Then
If Not SerialPort.IsOpen Then
MsgBox("串口未打开")
Return
End If
ToolStripButton3.Text = "停止校时"
ToolStripButton3.ForeColor = Color.Red
IsRuningTest = True
IsStopTest = False
isnotSendNode = True
IsSetTime = False
IsRtcTime = False
SendNodeDic.Clear()
Label38.ForeColor = Color.Yellow
If ProcessTable.Rows = 1 Then
' MsgBox("命令列表为空!!!")
Label38.Text = "命令列表为空!!!"
Label38.ForeColor = Color.Red
Return
End If
For i = 1 To ProcessTable.Rows - 1
If ProcessTable.Cell(i, 1).Text = "1" Then
' ProcessTable.Rows = ProcessTable.Rows - 1
SendNodeDic.Add((ProcessTable.Cell(i, 2).Text, New SendNode()))
End If
Next
Button24.PerformClick()
'运行线程如果 线程不存在则新建线程并运行如果线程存在中则先终止再新启动
If StartSendThread Is Nothing OrElse StartSendThread.ThreadState = ThreadState.Stopped Then
StartSendThread = New Thread(AddressOf StartSendThreadRuning)
StartSendThread.Start()
Else
StartSendThread.Abort()
StartSendThread = New Thread(AddressOf StartSendThreadRuning)
StartSendThread.Start()
End If
Else
ToolStripButton3.Text = "开始校时"
ToolStripButton3.ForeColor = Color.Black
IsRuningTest = False
IsStopTest = True
End If
End Sub
Delegate Sub delegateRefreshCaptureText(Textcolor As Color Textstr As String)
Public Sub RefreshCaptureText(Textcolor As Color Textstr As String)
If Me.InvokeRequired = True Then
Dim dd As New delegateRefreshCaptureText(AddressOf RefreshCaptureText)
Me.Invoke(dd, {Textcolor, Textstr})
Else
If Textcolor = Color.Red Then
Label38.Text = "失败"
Label38.ForeColor = Textcolor
Else
If Textcolor = Color.Green Then
If Textstr.Contains("校时完成") Then
Label38.Text = "成功"
Label38.ForeColor = Textcolor
Else
Label38.Text = "校时中"
Label38.ForeColor = Color.Yellow
End If
End If
End If
'Label38.Text = Textstr
End If
End Sub
Public Sub RefreshCaptureRichText(Textcolor As Color Textstr As String)
If Me.InvokeRequired = True Then
Dim dd As New delegateRefreshCaptureText(AddressOf RefreshCaptureRichText)
Me.Invoke(dd, {Textcolor, Textstr})
Else
RichTextBox1.Text = Textstr
Label38.ForeColor = Textcolor
End If
End Sub
Public Sub StartSendThreadRuning()
' SendPortData1()
Dim result As String = String.Empty
Dim nextnode As SendNode
For Each node In SendNodeDic
Console.WriteLine(node.Item1)
If node.Item1.Equals("读取RTC时间") Then
Console.WriteLine(node.Item1)
End If
If IsRuningTest = False Then Exit For
If isnotSendNode = False Then
RefreshCaptureText(Color.Red, "校时失败!!")
IsRuningTest = False
Exit For
End If
'循环等待节点接收状态改变
While node.Item2.RecvStatus = SendNode.RecvStatusEnum.None
If IsRuningTest = False Then Exit For
If node.Item1.Equals("延时") Then
node.Item2.AddRecvData(CommandSetDic.Item("延时"))
node.Item2.ResendRefresh()
Thread.Sleep(CInt(CommandSetDic.Item("延时")(0)) * 1000)
node.Item2.RecvRefresh(CommandSetDic.Item("延时"))
Exit While
End If
If node.Item1.Equals("获取服务器key") Then
node.Item2.AddRecvData({0})
node.Item2.ResendRefresh()
AppendTipText($"Com-TX:( {Now:HH:mm:ss:fff}):获取服务器key" & vbCrLf, Color.Green)
'从 后往前 遍历 SendNodeDic 列表
Dim ifnode As (String, SendNode)
For i As Integer = SendNodeDic.Count - 1 To 0 Step -1
ifnode = SendNodeDic(i)
If ifnode.Item1.Equals("读取软件版本号") AndAlso ifnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Exit For
End If
Next
If Not IsNothing(ifnode) AndAlso ifnode.Item1.Equals("读取软件版本号") AndAlso ifnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Dim MachineType As Integer
Dim Brandld As Integer
Dim buff As Byte() = ifnode.Item2.RecvDataLisr(0)
MachineType = CombineTwoBytesToDecimal(buff(7), buff(8))
Brandld = CombineTwoBytesToDecimal(buff(9), buff(10))
Dim uuid As String = ""
For ni As Integer = 1 To buff(13)
uuid += $"{Hex2(buff(13 + ni))} "
Next
uuid = uuid.Replace(" ", "")
Dim apinode As Program = API_AllocationBarCode(uuid, MachineType, Brandld)
If IsNothing(apinode) Then
Else
AppendTipText($"Com-TX:( {Now:HH:mm:ss:fff}):获取服务器ClientId{apinode.Response.ClientId}key:{apinode.Response.SecretKey}" & vbCrLf, Color.Blue)
node.Item2.RecvDatadic = apinode
node.Item2.RecvRefresh({0})
End If
Else
IsRuningTest = False '退出流程
RefreshCaptureText(Color.Red, $"节点:{node.Item1} :执行失败!")
Exit While
End If
End If
If node.Item1.Equals("设置设备key") Then
Dim ifnode As (String, SendNode)
Dim Nfnode As (String, SendNode)
For i As Integer = SendNodeDic.Count - 1 To 0 Step -1
If IsNothing(ifnode) Then
ifnode = SendNodeDic(i)
If ifnode.Item1.Equals("获取服务器key") AndAlso ifnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Else
ifnode = Nothing
End If
End If
If IsNothing(Nfnode) Then
Nfnode = SendNodeDic(i)
If Nfnode.Item1.Equals("读取设备key") AndAlso Nfnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Else
Nfnode = Nothing
End If
End If
Next
If Not IsNothing(ifnode.Item2) AndAlso Not IsNothing(Nfnode.Item2) Then
Dim devkey As Integer
Dim devClientId As String
Dim buff = Nfnode.Item2.RecvDataLisr(0)
Dim src As Byte() = Slice(buff, 5, 4)
devkey = BytesLE4ToInt(src)
src = Slice(buff, 9, buff(1) - 10)
devClientId = BytesToString(src).Trim
Dim apinode As Program = ifnode.Item2.RecvDatadic
If apinode.Response.SecretKey.Equals(devkey.ToString) AndAlso apinode.Response.ClientId.Equals(devClientId) Then
AppendTipText($"Com-TX:( {Now:HH:mm:ss:fff}):获取服务器ClientId{apinode.Response.ClientId}key:{apinode.Response.SecretKey}" & vbCrLf, Color.Blue)
node.Item2.RecvRefresh({0})
Exit While
End If
End If
End If
'判断发送状态是否改变0未发送1发送成功2发送失败
If node.Item2.SendStatus = SendNode.SendStatusEnum.None Then
'发送数据并更新发送状态
result = SendPortData1(node.Item1, node.Item2)
AppendTipText($"Com-TX:【{node.Item1}】", Color.Green)
AppendTipText("(" & Now.ToString("yyyy-MM-dd HH:mm:ss") & "):", Color.Black)
AppendTipText(ByteToString(node.Item2.SendData) & vbCrLf, Color.Green)
If String.IsNullOrEmpty(result) Then
result = $"节点:{node.Item1} :发送成功!"
RefreshCaptureText(Color.Green, result)
Else
IsRuningTest = False '退出流程
RefreshCaptureText(Color.Red, result)
End If
Else
'判断节点是否需要重新发送
If node.Item2.NeedResend() Then
result = SendPortData1(node.Item1, node.Item2)
AppendTipText("Com-TX:", Color.Green)
AppendTipText("(" & Now.ToString("yyyy-MM-dd HH:mm:ss") & "):", Color.Black)
AppendTipText(ByteToString(node.Item2.SendData) & vbCrLf, Color.Green)
If String.IsNullOrEmpty(result) Then
result = $"节点:{node.Item1} :重发[{ node.Item2.SendCount}] 送成功!"
RefreshCaptureText(Color.Green, result)
Else
IsRuningTest = False '退出流程
RefreshCaptureText(Color.Red, result)
End If
Else
If node.Item2.SendCount < 3 Then
Else
IsRuningTest = False '退出流程
RefreshCaptureText(Color.Red, $"节点:{node.Item1} :发送失败!")
End If
End If
End If
'延时(100)
Thread.Sleep(100)
End While
Next
'数据入库
Dim sresult As String = StoreTestDataInTheDatabase()
If String.IsNullOrEmpty(sresult) Then
If IsRuningTest = True Then
RefreshCaptureText(Color.Green, "校时完成!")
End If
Else
RefreshCaptureText(Color.Red, sresult)
End If
delToolStripButton3()
End Sub
Public Shared Function API_AllocationBarCode(Mcu_Uuid As String, MachineType As Integer, Brandld As Integer) As Program
Dim jsonString As String = String.Empty
Dim dic As New Dictionary(Of String String
dic.Add("Mcu_Uuid", Mcu_Uuid)
dic.Add("MachineType", MachineType)
dic.Add("Brandld", Brandld)
Dim jsonstr As String = JsonConvert.SerializeObject(dic)
Try
jsonString = PostData2("http://iot.uts-data.com:8086/api/Deviceinfoes/GetOrUpdateDevice", $"{jsonstr}")
Catch ex As Exception
MsgBox($"网络API调用错误请联系管理员。")
Return Nothing
End Try
''Console.WriteLine(jsonString)
If jsonString = Nothing Then
Return Nothing
End If
Dim login As Program
Try
login = JsonConvert.DeserializeObject(Of Program)(jsonString)
If Not IsNothing(login) AndAlso Not IsNothing(login.IsOk) Then
If login.IsOk Then
Return login
Else
Return Nothing
End If
Return Nothing
Else
Return Nothing
End If
Catch ex As Exception
MsgBox($"Json数据转换错误请联系管理员。详情 Json data to AllocationAPI error")
Return Nothing
End Try
End Function
Public Shared Function PostData2(ByVal url As String, ByVal data As String) As String
ServicePointManager.Expect100Continue = False
Dim request As HttpWebRequest = WebRequest.Create(url)
'//Post请求方式
request.Method = "POST"
'内容类型
request.ContentType = "application/json"
'将URL编码后的字符串转化为字节
Dim encoding As New UTF8Encoding()
Dim bys As Byte() = encoding.GetBytes(data)
'设置请求的 ContentLength
request.ContentLength = bys.Length
'获得请 求流
Dim newStream As Stream = request.GetRequestStream()
newStream.Write(bys, 0, bys.Length)
newStream.Close()
'获得响应流
Dim sr As StreamReader = New StreamReader(request.GetResponse().GetResponseStream)
Return sr.ReadToEnd
End Function
Public Shared Function PostData(ByVal url As String, ByVal data As String) As String
ServicePointManager.Expect100Continue = False
Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
'//Post请求方式
request.Method = "POST"
'内容类型
request.ContentType = "application/x-www-form-urlencoded"
'将URL编码后的字符串转化为字节
Dim encoding As New UTF8Encoding()
Dim bys As Byte() = encoding.GetBytes(data)
'设置请求的 ContentLength
request.ContentLength = bys.Length
'获得请 求流
Dim newStream As Stream = request.GetRequestStream()
newStream.Write(bys, 0, bys.Length)
newStream.Close()
'获得响应流
Dim sr As StreamReader = New StreamReader(request.GetResponse().GetResponseStream)
Return sr.ReadToEnd
End Function
Delegate Sub delegateToolStripButton3()
Public Sub delToolStripButton3()
If Me.InvokeRequired = True Then
Dim dd As New delegateToolStripButton3(AddressOf delToolStripButton3)
Me.Invoke(dd)
Else
ToolStripButton3.Text = "开始校时"
ToolStripButton3.ForeColor = Color.Black
IsRuningTest = False
IsStopTest = True
End If
End Sub
'byte 转16进制字符串
Public Function Hex2(ByVal b As Byte) As String
Return b.ToString("X2")
End Function
'测试数据入库
Public Function StoreTestDataInTheDatabase() As String
'判断测试是主动停止还是被动停止
Dim result As String = String.Empty
If IsStopTest = True Then
result = "测试被停止!"
Return result
End If
Dim dic As New Dictionary(Of String, String)
Dim buff() As Byte
dic.Add("测试时间", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
dic.Add("测试结果", "1")
dic.Add("测试信息", "成功")
If IsSetTime = True Then
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"失败:设置生产时间失败!"
result = $"失败:设置生产时间失败!"
RefreshCaptureText(Color.Red, "失败:设置生产时间失败!")
End If
If IsRtcTime = True Then
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"失败设备RTC时钟故障"
result = $"失败设备RTC时钟故障"
RefreshCaptureText(Color.Red, "失败设备RTC时钟故障")
End If
Dim node As (String, SendNode)
For i = 0 To SendNodeDic.Count - 1
node = SendNodeDic(i)
If node.Item1.Equals("延时") Then
Continue For
End If
If node.Item1.Equals("获取服务器key") Then
'[服务器key] Text
' ' [服务器ClientId] TEXT
Dim apinode As Program = node.Item2.RecvDatadic
dic.Add("服务器key", apinode.Response.SecretKey)
dic.Add("服务器ClientId", apinode.Response.ClientId)
Continue For
End If
If node.Item2.SendStatus = SendNode.SendStatusEnum.Send Then
If &H2 = node.Item2.SendData(3) Then
'判断接收状态是否为成功
If node.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
buff = node.Item2.RecvDataLisr(0)
If node.Item2.SendData(3) = buff(3) AndAlso node.Item2.SendData(4) = buff(4) Then
Try
Select Case buff(4)
Case 1 '读取RTC时间
'AppendTipText($"RTC: 20{Hex(buff(6))}-{Hex(buff(7))}-{Hex(buff(8))} {Hex(buff(9))}:{Hex(buff(10))}:{Hex(buff(11))} {Hex(buff(12))} " & vbCrLf, Color.Blue)
dic.Add("RTC时间", $"20{Hex2(buff(6))}-{Hex2(buff(7))}-{Hex2(buff(8))} {Hex2(buff(9))}:{Hex2(buff(10))}:{Hex2(buff(11))}")
dic.Add("RTC星期", $"{Hex(buff(12))}")
Case 2 '读取设置参数信息
'00 - 读取校准结果0x00:校准成功, 其他值: 校准失败
' 1E 00 稳定消抖时间 - 单位s
'2C 01 背景值滤波长度 - 单位s
' FA 0F 传感器极大值
' 0A 00 传感器极小值
' 03 00 预热时间 - 单位:分钟
'34 08 LEV 10% 对应的ADC 值
' 20 03 LEV 0% 对应的ADC 值
' 96 00 触发 - 消抖次数
' 96 00 释放 - 消抖次数
' 64 00 稳定阈值
' 32 00 报警点提前量
' B0 4 校准超时 - 单位: S
'14 00 LEV 0% 校准最小值
' AC 0D LEV 0% 校准最大值
' F4 1 LEV 10% 校准最小值
' FA 0F LEV 10% 校准最大值
' 14 00 差值 校准最小值
' FA 0F 差值 校准最大值
' C8 0 泄露恢复正常 判定条件1 处于基准的XX倍数以内
'05 00 泄露恢复正常 判定条件1处于基准的XX倍数以内的消抖时间 单位: 秒
'84 03 泄露恢复正常 判定条件2处于基准的XX倍数以内
'78 00 泄露恢复正常 判定条件2处于基准的XX倍数以内的消抖时间 单位: 分钟
'DC 63 E6 67 设备生产时间
If dic.ContainsKey("校准结果") Then
Select Case buff(5)
Case 0
dic("校准结果") = $"{(buff(5))}_OK"
Case 1
dic("校准结果") = $"{(buff(5))}_未校准"
Case 2
dic("校准结果") = $"{(buff(5))}_校验错误"
End Select
dic("温度校准算法选择") = CombineTwoBytesToDecimal(buff(6), buff(7))
dic("回差") = CombineTwoBytesToDecimal(buff(8), buff(9))
dic("传感器极大值") = CombineTwoBytesToDecimal(buff(10), buff(11))
dic("传感器极小值") = CombineTwoBytesToDecimal(buff(12), buff(13))
dic("预热时间_分") = CombineTwoBytesToDecimal(buff(14), buff(15))
dic("ADC_LEV_10") = CombineTwoBytesToDecimal(buff(16), buff(17))
dic("ADC_LEV_0") = CombineTwoBytesToDecimal(buff(18), buff(19))
dic("触发_消抖次数") = CombineTwoBytesToDecimal(buff(20), buff(21))
dic("释放_消抖次数") = CombineTwoBytesToDecimal(buff(22), buff(23))
dic("稳定阈值") = CombineTwoBytesToDecimal(buff(24), buff(25))
dic("报警点提前量") = CombineTwoBytesToDecimal(buff(26), buff(27))
dic("校准超时_秒") = CombineTwoBytesToDecimal(buff(28), buff(29))
dic("IHIOT_心跳包上报间隔") = CombineTwoBytesToDecimal(buff(30), buff(31))
dic("OSD显示模式") = CombineTwoBytesToDecimal(buff(32), buff(33))
dic("检测故障最小值") = CombineTwoBytesToDecimal(buff(34), buff(35))
dic("检测故障最大值") = CombineTwoBytesToDecimal(buff(36), buff(37))
dic("校准最小值_LEV_0") = CombineTwoBytesToDecimal(buff(38), buff(39))
dic("校准最大值_LEV_0") = CombineTwoBytesToDecimal(buff(40), buff(41))
dic("校准最小值_LEV_10") = CombineTwoBytesToDecimal(buff(42), buff(43))
dic("校准最大值_LEV_10") = CombineTwoBytesToDecimal(buff(44), buff(45))
dic("校准最小值_差值") = CombineTwoBytesToDecimal(buff(46), buff(47))
dic("校准最大值_差值") = CombineTwoBytesToDecimal(buff(48), buff(49))
dic("自定义LEV_10_对应的ADC") = CombineTwoBytesToDecimal(buff(50), buff(51))
dic("自定义LEV_0_对应的ADC") = CombineTwoBytesToDecimal(buff(52), buff(53))
dic("泄露恢复正常_条件2") = CombineTwoBytesToDecimal(buff(54), buff(55))
dic("泄露恢复正常_条件2消抖时间_分") = CombineTwoBytesToDecimal(buff(56), buff(57))
dic("设备生产时间") = CombineFourBytesToLong(buff(61), buff(60), buff(59), buff(58))
Else
dic.Add("校准结果", $"{(buff(5))}")
dic("温度校准算法选择") = CombineTwoBytesToDecimal(buff(6), buff(7))
dic("回差") = CombineTwoBytesToDecimal(buff(8), buff(9))
dic("传感器极大值") = CombineTwoBytesToDecimal(buff(10), buff(11))
dic("传感器极小值") = CombineTwoBytesToDecimal(buff(12), buff(13))
dic("预热时间_分") = CombineTwoBytesToDecimal(buff(14), buff(15))
dic("ADC_LEV_10") = CombineTwoBytesToDecimal(buff(16), buff(17))
dic("ADC_LEV_0") = CombineTwoBytesToDecimal(buff(18), buff(19))
dic("触发_消抖次数") = CombineTwoBytesToDecimal(buff(20), buff(21))
dic("释放_消抖次数") = CombineTwoBytesToDecimal(buff(22), buff(23))
dic("稳定阈值") = CombineTwoBytesToDecimal(buff(24), buff(25))
dic("报警点提前量") = CombineTwoBytesToDecimal(buff(26), buff(27))
dic("校准超时_秒") = CombineTwoBytesToDecimal(buff(28), buff(29))
dic("IHIOT_心跳包上报间隔") = CombineTwoBytesToDecimal(buff(30), buff(31))
dic("OSD显示模式") = CombineTwoBytesToDecimal(buff(32), buff(33))
dic("检测故障最小值") = CombineTwoBytesToDecimal(buff(34), buff(35))
dic("检测故障最大值") = CombineTwoBytesToDecimal(buff(36), buff(37))
dic("校准最小值_LEV_0") = CombineTwoBytesToDecimal(buff(38), buff(39))
dic("校准最大值_LEV_0") = CombineTwoBytesToDecimal(buff(40), buff(41))
dic("校准最小值_LEV_10") = CombineTwoBytesToDecimal(buff(42), buff(43))
dic("校准最大值_LEV_10") = CombineTwoBytesToDecimal(buff(44), buff(45))
dic("校准最小值_差值") = CombineTwoBytesToDecimal(buff(46), buff(47))
dic("校准最大值_差值") = CombineTwoBytesToDecimal(buff(48), buff(49))
dic("自定义LEV_10_对应的ADC") = CombineTwoBytesToDecimal(buff(50), buff(51))
dic("自定义LEV_0_对应的ADC") = CombineTwoBytesToDecimal(buff(52), buff(53))
dic("泄露恢复正常_条件2") = CombineTwoBytesToDecimal(buff(54), buff(55))
dic("泄露恢复正常_条件2消抖时间_分") = CombineTwoBytesToDecimal(buff(56), buff(57))
dic("设备生产时间") = CombineFourBytesToLong(buff(61), buff(60), buff(59), buff(58))
End If
Case 3 '读取软件版本号
'04 软件版本号
'03 硬件板本号
' 78 00 3E 00 0F 80 13 11 0C 80 UUID
dic.Add("软件版本号", $"{Hex(buff(5))}")
dic.Add("硬件版本号", $"{Hex(buff(6))}")
dic.Add("设备类型ID", CombineTwoBytesToDecimal(buff(7), buff(8)))
dic.Add("厂牌ID", CombineTwoBytesToDecimal(buff(9), buff(10)))
dic.Add("机型ID", CombineTwoBytesToDecimal(buff(11), buff(12)))
Dim uuid As String = ""
For ni As Integer = 1 To buff(13)
uuid += $"{Hex2(buff(13 + ni))} "
Next
dic.Add("UUID", $"{uuid}")
Case 4 '读取实时状态
' 02 00 状态机 - 正常监控 类型int16_t
' C6 1 实时值 - 类型int16_t
' C9 1 背景值 - 类型int16_t
' C6 1 基底值 - 类型int16_t
' FD FF 差值 - 类型int16_t
' 00 00 LEL百分比 - 类型int16_t
' 01 00 稳定状态 - 类型int16_t
' 0E A2 基底值差值百分比1 - 类型int16_t
' 3B A4 基底值+差值百分比2 - 类型int16_t
' 4C 00 温度 - 类型int16_t
dic.Add("状态机", ReadTheStatus(CombineTwoBytesToDecimal(buff(5), buff(6))))
dic.Add("实时值", CombineTwoBytesToDecimal(buff(7), buff(8)))
dic.Add("背景值", CombineTwoBytesToDecimal(buff(9), buff(10)))
dic.Add("基底值", CombineTwoBytesToDecimal(buff(11), buff(12)))
dic.Add("差值", CombineTwoBytesToDecimaShort(buff(13), buff(14)))
dic.Add("LEL百分比", CombineTwoBytesToDecimal(buff(15), buff(16)))
dic.Add("稳定状态", CombineTwoBytesToDecimal(buff(17), buff(18)))
dic.Add("基底值差值百分比1", CombineTwoBytesToDecimal(buff(20), buff(19)))
dic.Add("基底值差值百分比2", CombineTwoBytesToDecimal(buff(22), buff(21)))
dic.Add("温度", CombineTwoBytesToDecimal(buff(23), buff(24)))
Case 9 '读设备 key
'[服务器key] Text
' [服务器ClientId] TEXT
Dim src As Byte() = Slice(buff, 5, 4)
If dic.ContainsKey("设备ClientId") Then
dic.Item("设备ClientId") = BytesLE4ToInt(src)
Else
dic.Add("设备ClientId", BytesLE4ToInt(src))
End If
src = Slice(buff, 9, buff(1) - 10)
If dic.ContainsKey("设备key") Then
dic.Item("设备key") = BytesToString(src)
Else
dic.Add("设备key", BytesToString(src))
End If
Case Else
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"节点:{node.Item1} :接收数据未找到对应解析方式!"
result = $"节点:{node.Item1} :接收数据未找到对应解析方式!"
Exit For
End Select
Catch ex As Exception
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"节点:{node.Item1} :接收数据异常!"
result = $"节点:{node.Item1} :接收数据异常!"
Exit For
End Try
Else
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"节点:{node.Item1} :接收数据异常!"
result = $"节点:{node.Item1} :接收数据异常!"
Exit For
End If
Else
'接收失败
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"节点:{node.Item1} :接收失败!"
result = $"节点:{node.Item1} :接收失败!"
Exit For
End If
End If
Else
If node.Item2.SendStatus = SendNode.SendStatusEnum.None Then
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"失败 :设备无校准参数信息!"
result = $"失败 :设备无校准参数信息!"
ElseIf node.Item2.SendStatus = SendNode.SendStatusEnum.Timeout Then
dic.Item("测试结果") = "0"
dic.Item("测试信息") = $"节点:{node.Item1} :发送失败!"
result = $"节点:{node.Item1} :发送失败!"
End If
Exit For
End If
Next
Dim nstr As String = JsonConvert.SerializeObject(dic)
'入库
WriteToTable(dic)
Dim localConn As New DbConnectionStringBuilder
localConn.Add("Data Source", Sqlitedbpath)
Using db As New DbExecutor(DbExecutor.DbTypeEnum.Sqlite, localConn.ToString())
Try
db.Open()
Dim caint = db.ExecuteNonQuery(db.CmdHelper.Insert(SqliteTableName, dic))
If caint = 0 Then
result = "Sqlite入库失败"
End If
db.Close()
Catch ex As Exception
result = $"Sqlite入库失败{ex.Message}"
End Try
db.Close()
' Return True
End Using
Using db As New DbExecutor(DbExecutor.DbTypeEnum.Mysql, DbConnString)
Try
db.Open()
Dim caint = db.ExecuteNonQuery(db.CmdHelper.Insert(SqliteTableName, dic))
If caint = 0 Then
result = "Mysql入库失败"
End If
db.Close()
Catch ex As Exception
result = $"Mysql入库失败{ex.Message}"
End Try
db.Close()
' Return True
End Using
Return result
End Function
''' <summary>
''' 将 Byte 数组按 UTF-8 编码转成字符串。
''' </summary>
Public Function BytesToString(buf As Byte()) As String
If buf Is Nothing Then Return ""
Return System.Text.Encoding.UTF8.GetString(buf)
End Function
''' <summary>
''' 从原数组截取部分数据为新数组。
''' </summary>
''' <param name="source">源数组</param>
''' <param name="start">起始索引0 起算)</param>
''' <param name="length">要截取的长度</param>
Public Function Slice(Of T)(source As T(), start As Integer, length As Integer) As T()
If source Is Nothing Then Return Nothing
If start < 0 OrElse length <= 0 OrElse start + length > source.Length Then Return New T(-1) {}
Dim dest(length - 1) As T
Array.Copy(source, start, dest, 0, length)
Return dest
End Function
''' <summary>
''' 将 Byte 数组按指定编码转成字符串。
''' 缺省编码为 UTF-8。
''' </summary>
''' <param name="bytes">源数组</param>
''' <param name="encoding">编码,省略则 UTF-8</param>
Public Function BytesToString(bytes As Byte(),
Optional encoding As Text.Encoding = Nothing) As String
If bytes Is Nothing OrElse bytes.Length = 0 Then Return ""
If encoding Is Nothing Then encoding = System.Text.Encoding.UTF8
Return encoding.GetString(bytes)
End Function
Public Function BytesLE4ToInt(buf As Byte()) As Integer
If buf Is Nothing OrElse buf.Length < 4 Then Return 0
Return buf(0) Or (buf(1) << 8) Or (buf(2) << 16) Or (buf(3) << 24)
End Function
'创建slqit
Public Sqlitedbpath As String = FileCPatrh & "\SQlitedb\test.db"
Public SqliteTableName As String = "NT318"
Public Function ClearDeviceform() As Boolean
Dim localConn As New DbConnectionStringBuilder
localConn.Add("Data Source", Sqlitedbpath)
'localConn.Add("Password", "123456")
Dim LocalConnString = localConn.ToString()
'判断有没有文件夹
If Not Directory.Exists(FileCPatrh & "\SQlitedb\") Then
Directory.CreateDirectory(FileCPatrh & "\SQlitedb\")
End If
Dim selectstr As String = $"CREATE TABLE IF NOT EXISTS {SqliteTableName} (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 替代 BIGINT AUTO_INCREMENT
`测试时间` TEXT NOT NULL, -- DATETIME → TEXT (ISO-8601)
`测试结果` INTEGER NOT NULL,
`测试信息` TEXT NOT NULL,
`软件版本号` TEXT NOT NULL,
`硬件版本号` TEXT NOT NULL,
`设备类型ID` INTEGER NOT NULL,
`厂牌ID` INTEGER NOT NULL,
`机型ID` INTEGER NOT NULL,
`UUID` TEXT NOT NULL,
`设备key` TEXT NOT NULL,
`设备ClientId` INTEGER NOT NULL,
`服务器key` TEXT NOT NULL,
`服务器ClientId` INTEGER NOT NULL,
`状态机` TEXT NOT NULL,
`实时值` INTEGER NOT NULL,
`背景值` INTEGER NOT NULL,
`基底值` INTEGER NOT NULL,
`差值` INTEGER NOT NULL,
`LEL百分比` INTEGER NOT NULL,
`稳定状态` INTEGER NOT NULL,
`基底值差值百分比1` INTEGER NOT NULL,
`基底值差值百分比2` INTEGER NOT NULL,
`温度` INTEGER NOT NULL,
`校准结果` INTEGER NOT NULL,
`温度校准算法选择` INTEGER NOT NULL,
`回差` INTEGER NOT NULL,
`传感器极大值` INTEGER NOT NULL,
`传感器极小值` INTEGER NOT NULL,
`预热时间_分` INTEGER NOT NULL,
`ADC_LEV_10` INTEGER NOT NULL,
`ADC_LEV_0` INTEGER NOT NULL,
`触发_消抖次数` INTEGER NOT NULL,
`释放_消抖次数` INTEGER NOT NULL,
`稳定阈值` INTEGER NOT NULL,
`报警点提前量` INTEGER NOT NULL,
`校准超时_秒` INTEGER NOT NULL,
`IHIOT_心跳包上报间隔` INTEGER NOT NULL,
`OSD显示模式` INTEGER NOT NULL,
`检测故障最小值` INTEGER NOT NULL,
`检测故障最大值` INTEGER NOT NULL,
`校准最小值_LEV_0` INTEGER NOT NULL,
`校准最大值_LEV_0` INTEGER NOT NULL,
`校准最小值_LEV_10` INTEGER NOT NULL,
`校准最大值_LEV_10` INTEGER NOT NULL,
`校准最小值_差值` INTEGER NOT NULL,
`校准最大值_差值` INTEGER NOT NULL,
`自定义LEV_10_对应的ADC` INTEGER NOT NULL,
`自定义LEV_0_对应的ADC` INTEGER NOT NULL,
`泄露恢复正常_条件2` INTEGER NOT NULL,
`泄露恢复正常_条件2消抖时间_分` INTEGER NOT NULL,
`设备生产时间` TEXT NOT NULL,
`RTC时间` TEXT NOT NULL,
`RTC星期` INTEGER NOT NULL,
created_at TEXT DEFAULT (datetime('now'))
);"
Dim dt As DataTable
Try
Using db As New DbExecutor(DbExecutor.DbTypeEnum.Sqlite, LocalConnString)
db.Open()
'Try
' 'Dim vselectstr = $"DELETE FROM {Tftp_Log};"
' 'db.ExecuteNonQuery(vselectstr)
'Catch ex As Exception
'End Try
dt = db.ExecuteDataTable(selectstr)
db.Close()
If IsNothing(dt) Then
MsgBox($"数据表创建失败!!!{vbCrLf }")
Return False
Else
Return True
End If
Return True
End Using
Catch ex As Exception
MsgBox($"数据表创建失败!!!{vbCrLf }原因:{vbCrLf }{ex.Message }")
Return False
End Try
End Function
Delegate Sub DelegateWriteToTable(dic As Dictionary(Of String, String))
'写入到表格
Private Sub WriteToTable(dic As Dictionary(Of String, String))
If Me.InvokeRequired = True Then
Dim dd As New DelegateWriteToTable(AddressOf WriteToTable)
Me.Invoke(dd, {dic})
Else
Grid_table.AddItem("")
Dim con As Integer = 0
Dim str As String = String.Empty
For i = 1 To Grid_table.Cols - 1
str = Grid_table.Cell(0, i).Text
If dic.ContainsKey(str) Then
Grid_table.Cell(Grid_table.Rows - 1, i).Text = dic(str)
Else
con += 1
End If
Next
If dic.Item("测试结果") = "1" Then
Grid_table.Range(Grid_table.Rows - 1, 1, Grid_table.Rows - 1, Grid_table.Cols - 1).ForeColor = Color.Green
Grid_table.Range(Grid_table.Rows - 1, 1, Grid_table.Rows - 1, Grid_table.Cols - 1).FontBold = True
Else
Grid_table.Range(Grid_table.Rows - 1, 1, Grid_table.Rows - 1, Grid_table.Cols - 1).ForeColor = Color.Red
Grid_table.Range(Grid_table.Rows - 1, 1, Grid_table.Rows - 1, Grid_table.Cols - 1).FontBold = True
End If
End If
End Sub
'计算将4个字节合成 Long UTC秒值并转为时间戳
Private Function CombineFourBytesToLong(ByVal b1 As Byte, ByVal b2 As Byte, ByVal b3 As Byte, ByVal b4 As Byte) As String
'将4个字节合成 Long UTC秒值并转为时间戳
Dim temp_val As Long = b1 * 256 * 256 * 256 + b2 * 256 * 256 + b3 * 256 + b4
'计算UTC时间
Return $"{DateAndTime.DateSerial(1970, 1, 1).AddSeconds(temp_val).ToString("yyyy-MM-dd HH:mm:ss")}"
End Function
'将2个字节 合成十进制数
Private Function CombineTwoBytesToDecimal(ByVal b1 As Byte, ByVal b2 As Byte) As Integer
Return b2 * 256 + b1
End Function
Private Function CombineTwoBytesToDecimaShort(ByVal b1 As Byte, ByVal b2 As Byte) As Short
Dim s As Short = b2
s = s << 8
s += b1
Return s
End Function
'获取校准结果
Private Function ReadTheCalibrationResult(Statebyte As Byte) As String
If Statebyte = 0 Then
Return "0_校准成功"
Else
Return $"{Statebyte}_校准失败"
End If
End Function
'获取状态机状态
Private Function ReadTheStatus(Statebyte As Byte) As String
' 状态机
'#define DevAPP_PowerOn_Start 0x00 //设备状态 - 上电启动
'#define DevAPP_Preheat 0x01 //设备状态 - 预热
'#define DevAPP_Normal_Operation 0x02 //设备状态 - 正常监控
'#define DevAPP_Leak_Detected 0x03 //设备状态 - 检测到泄露
'#define DevAPP_Alarm 0x04 //设备状态 - 报警
'#define DevAPP_Malfunction 0x05 //设备状态 - 故障
'#define DevAPP_Expiration_Of_Life 0x06 //设备状态 - 寿命到期
'#define DevAPP_Calibration_Mode 0x07 //设备状态 - 校准模式
'#define DevAPP_Uncalibrated 0x08 //设备状态 - 未校准
'#define DevApp_Equipment_Outage 0x09 //设备状态 - 220V电源断开
'#define DevApp_SelfCheck_Mode 0x0A //设备状态 - 自检模式
'#define DevApp_Pairing_Mode 0x0B //设备状态 - 无线配对模式
Select Case Statebyte
Case &H0
Return $"{Hex(Statebyte)}_上电启动"
Case &H1
Return $"{Hex(Statebyte)}_预热"
Case &H2
Return $"{Hex(Statebyte)}_正常监控"
Case &H3
Return $"{Hex(Statebyte)}_检测到泄露"
Case &H4
Return $"{Hex(Statebyte)}_报警"
Case &H5
Return $"{Hex(Statebyte)}_故障"
Case &H6
Return $"{Hex(Statebyte)}_寿命到期"
Case &H7
Return $"{Hex(Statebyte)}_校准模式"
Case &H8
Return $"{Hex(Statebyte)}_未校准"
Case &H9
Return $"{Hex(Statebyte)}_220V电源断开"
Case &HA
Return $"{Hex(Statebyte)}_自检模式"
Case &HB
Return $"{Hex(Statebyte)}_无线配对模式"
End Select
End Function
Private Function SendPortData1(Name As String, node As SendNode) As String
Dim sendBytes As Byte()
Dim result As String = String.Empty
Try
'获取发送内容
sendBytes = GetSendPortData1(Name)
If sendBytes Is Nothing OrElse sendBytes.Length = 0 Then
result = $"节点:{Name} :发送数据为空!"
' RefreshCaptureText(Color.Red, result)
End If
'设置发送节点发送的数据
node.SetSendData(sendBytes)
SerialPort.Write(node.SendData, 0, node.SendData.Length)
'发送刷新对应数值
node.ResendRefresh()
'RefreshCaptureText(Color.Green, result)
Catch ex As Exception
result = $"发送:【{Name}】失败!{vbCrLf}详情:{vbCrLf}{ex.Message}"
'RefreshCaptureText(Color.Red, result)
End Try
Return result
End Function
'获取发送内容
Public RTC_Time As Date
Private Function GetSendPortData1(name As String) As Byte()
Dim sendBytes As Byte()
If name.Equals("设置RTC时间") Then
sendBytes = GetSetRTCTime()
ElseIf name.Equals("设置生产时间") Then
sendBytes = GetSetUTCTime()
ElseIf name.Equals("设置设备key") Then
sendBytes = SetDeviceKey()
ElseIf CommandSetDic.ContainsKey(name) Then
sendBytes = CommandSetDic.Item(name)
End If
Return sendBytes
End Function
Private Function SetDeviceKey() As Byte()
Dim li As New List(Of Byte)
li.Add(&HAE)
li.Add(&H0) '长度
li.Add(&H0) '校验
li.Add(&H1) '命令 - 设置参数
li.Add(&H9) '参数内容 - 设置RTC时间
Dim ifnode As (String, SendNode)
For i As Integer = SendNodeDic.Count - 1 To 0 Step -1
ifnode = SendNodeDic(i)
If ifnode.Item1.Equals("获取服务器key") AndAlso ifnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Exit For
End If
Next
If Not IsNothing(ifnode) AndAlso ifnode.Item1.Equals("获取服务器key") AndAlso ifnode.Item2.RecvStatus = SendNode.RecvStatusEnum.Recv Then
Dim apinode As Program = ifnode.Item2.RecvDatadic
li.AddRange(IntTo4BytesLE(apinode.Response.ClientId))
li.AddRange(StringToBytes(apinode.Response.SecretKey))
li.Add(&HEA)
li(1) = li.Count
li(2) = GetSumCheckMod(li.ToArray, li.Count)
Return li.ToArray
Else
Return Nothing
End If
End Function
Private Sub ToolStripButton2_Click(sender As Object, e As EventArgs) Handles ToolStripButton2.Click
Dim isvisible As Boolean = False
If ToolStripButton2.Text.Equals(">>") Then
'弹窗获取密码
Dim password As String = InputBox("请输入密码:", "密码验证")
If Not password.Trim.Equals("Cc2025OK") Then
Return
End If
isvisible = True
ToolStripButton2.Text = "<<"
Else
isvisible = False
ToolStripButton2.Text = ">>"
End If
GroupBox1.Visible = isvisible
ToolStripLabel1.Visible = isvisible
T_CommandAlias.Visible = isvisible
ToolStripLabel2.Visible = isvisible
ToolStripTextBox2.Visible = isvisible
ToolStripButton1.Visible = isvisible
ToolStripComboBox1.Visible = isvisible
SplitContainer4.Panel1Collapsed = Not isvisible
ComboBox9.Visible = isvisible
LblSerialPortBaud.Visible = isvisible
ToolStripButton4.Visible = isvisible
ToolStripButton5.Visible = isvisible
ToolStripButton6.Visible = isvisible
ToolStripLabel3.Visible = isvisible
ToolStripTextBox1.Visible = isvisible
'设置TabControl1 的第1、2个选项卡 显示状态为隐藏或显示
If (isvisible) Then
TabPage1.Parent = TabControl1
TabPage2.Parent = TabControl1
Else
TabPage1.Parent = Nothing
TabPage2.Parent = Nothing
End If
For i As Integer = 0 To Grid_table.Cols - 1
If i > 6 Then
Grid_table.Column(i).Visible = isvisible
End If
Next
End Sub
Private Sub ToolStripComboBox1_DropDown(sender As Object, e As EventArgs) Handles ToolStripComboBox1.DropDown
If IsNothing(CommandSetDic) OrElse CommandSetDic.Count = 0 Then Return
ToolStripComboBox1.Items.Clear()
ToolStripComboBox1.Items.AddRange(CommandSetDic.Keys.ToArray())
End Sub
Private Sub ProcessTable_CellChange(Sender As Object, e As Grid.CellChangeEventArgs) Handles ProcessTable.CellChange
'ProcessTable.Cell(0, 0).Text = "序号"
'ProcessTable.Cell(0, 1).Text = "勾选"
'ProcessTable.Cell(0, 2).Text = "命令别名"
'ProcessTable.Cell(0, 3).Text = "命令"
'ProcessTable.Cell(0, 4).Text = "发送状态"
If e.Row = 0 Then Return
Select Case e.Col
Case 2
If CommandSetDic.ContainsKey(ProcessTable.Cell(e.Row, 2).Text.Trim) Then
Dim strbuf() As Byte = CommandSetDic(ProcessTable.Cell(e.Row, 2).Text.Trim)
Dim str As String = ByteArrayToHexString(strbuf)
ProcessTable.Cell(e.Row, 3).Text = str
Else
MsgBox("命令别名不存在,请先添加别名和对应命令到命令集,再调用!!")
ProcessTable.Cell(e.Row, 2).Text = ""
End If
End Select
End Sub
Private Sub ToolStripButton5_Click(sender As Object, e As EventArgs) Handles ToolStripButton5.Click
If ProcessTable.ActiveCell.Row < 1 Then
ProcessTable.AddItem("")
Else
ProcessTable.InsertRow(ProcessTable.ActiveCell.Row, 1)
End If
End Sub
Private Sub ToolStripButton6_Click(sender As Object, e As EventArgs) Handles ToolStripButton6.Click
If ProcessTable.ActiveCell.Row < 1 Then
ProcessTable.Row(ProcessTable.Rows - 1).Delete()
Else
ProcessTable.Row(ProcessTable.ActiveCell.Row).Delete()
End If
End Sub
Private Sub ToolStripButton4_Click(sender As Object, e As EventArgs) Handles ToolStripButton4.Click
InitLoadProcessTable(False)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
My.Settings.SerialPortName = ComboBox8.Text
My.Settings.SInTime = ToolStripTextBox1.Text
My.Settings.Save()
Timer2.Stop()
Timer1.Stop()
SaveCommandSetDic()
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Label39.Text = Now.ToString("yyyy-MM-dd")
Label40.Text = Now.ToString("HH:mm:ss")
Select Case Now.DayOfWeek
Case 0, 7
Label41.Text = "星期日"
Case 1
Label41.Text = "星期一"
Case 2
Label41.Text = "星期二"
Case 3
Label41.Text = "星期三"
Case 4
Label41.Text = "星期四"
Case 5
Label41.Text = "星期五"
Case 6
Label41.Text = "星期六"
End Select
'Label41.Text = $"星期{ Now.DayOfWeek }"
End Sub
Public Timediffe As Integer = 2
Private Sub ToolStripTextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ToolStripTextBox1.KeyPress
'限制输入只能为数字
If e.KeyChar < "0"c OrElse e.KeyChar > "9"c Then
e.Handled = True
End If
End Sub
Private Sub ToolStripTextBox1_TextChanged(sender As Object, e As EventArgs) Handles ToolStripTextBox1.TextChanged
If Integer.TryParse(ToolStripTextBox1.Text, Timediffe) Then
Else
ToolStripTextBox1.Text = "2"
Timediffe = 2
End If
End Sub
#End Region
End Class
Public Class SendNode
'发送时间
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 RecvDatadic As Object
Sub New()
RecvDataLisr = New List(Of Byte())
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)
SendData = Mysenddata
SendInterval = 0
SendTimeout = 1000
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 < 3 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
End Class