Files
Desktop_TelephoneTools/Telephone.vb

688 lines
27 KiB
VB.net
Raw Normal View History

2025-12-11 14:07:27 +08:00
Imports System.IO.Ports
Imports System.Text
Imports System.Threading
Imports Newtonsoft.Json
Imports StackExchange.Redis
Imports Telephone.PhoneBurstification
Public Class Telephone
'hex 发送标志
Public G_Hexflg As Boolean = False
'订阅字段
Public G_Subscribe As String = ""
Public G_OldSubscribe As String = ""
'发布字段
Public G_Publish As String = ""
'
Public G_RedisSub, G_Redislish As RedisSubscriber
'redis消息队列
Public M_RedisQueue As Queue
'事件处理线程
Public M_EventThread As Thread
'
Public G_SendBuffnode As SendBuffnode
'日志对象
Public G_Log As RuningLog
Private Sub Telephone_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'设置页面标题为软件名称加版本号
Me.Text = Application.ProductName & " " & Application.ProductVersion
G_Hexflg = False
recvBufferli = New List(Of Byte)()
G_Log = New RuningLog(RichTextBox1, Application.StartupPath & "\log")
ComboBox1.Items.Clear()
ComboBox1.Items.AddRange(SerialPort.GetPortNames())
GetSeting()
initRedisSubscriber(G_Subscribe, G_OldSubscribe)
initRedisPublisher()
M_RedisQueue = New Queue()
M_EventThread = New Thread(AddressOf EventThread)
M_EventThread.Start()
Button1.PerformClick()
End Sub
Public Sub EventThread()
Dim msgCount As Integer
'获取发短信的集合并且按时间排序
Dim sendShortMessagesLi As New List(Of CallInfoNode)
Dim callLi As New List(Of CallInfoNode)
Dim item As CallInfoNode
While True
If M_RedisQueue.Count > 0 Then
'遍历队列
msgCount = M_RedisQueue.Count
sendShortMessagesLi.Clear()
callLi.Clear()
For i As Integer = 0 To msgCount - 1
item = M_RedisQueue.Dequeue()
If IsNothing(item) Then Continue For
If item.Type.Trim.Equals("1") Then
callLi.Add(item)
ElseIf item.Type.Trim.Equals("2") Then
sendShortMessagesLi.Add(item)
End If
Next
'判断是否有短信发送
If sendShortMessagesLi.Count > 0 Then
'发送短信
SendShortMessage(sendShortMessagesLi)
sendShortMessagesLi.Clear()
End If
'判断是否有电话拨号
If callLi.Count > 0 Then
'拨打电话
CallPhone(callLi)
callLi.Clear()
End If
End If
Thread.Sleep(10)
End While
End Sub
'发送短信
Public Sub SendShortMessage(sendShortMessagesLi As List(Of CallInfoNode))
'遍历sendShortMessagesLi
Dim gLogNode As LogNode
For Each item In sendShortMessagesLi
'获取当前时间的utc秒值
Dim nowt As Long = CLng(DateTime.UtcNow.Subtract(New DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds)
'判断是否超时
If item.DeadLine < nowt Then
Continue For
End If
gLogNode = New LogNode($"开始执行{item.CallerName}发送短信:{item.PhoneNumber}", RuningLog.LogType.e_info, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
If ProcessshortmessagesData(item) Then
RedisPublishMessage($"执行{item.CallerName}发送短信:{item.PhoneNumber}成功")
gLogNode = New LogNode($"执行{item.CallerName}发送短信:{item.PhoneNumber}成功", RuningLog.LogType.e_info, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
Else
RedisPublishMessage($"执行{item.CallerName}发送短信:{item.PhoneNumber}失败")
gLogNode = New LogNode($"执行{item.CallerName}发送短信:{item.PhoneNumber}失败", RuningLog.LogType.e_Error, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
End If
Next
End Sub
Public Function ProcessshortmessagesData(CallInfoNode As CallInfoNode) As Boolean
Dim li As List(Of SendBuffnode)
Dim gLogNode As LogNode
Dim SendData As Byte()
li = PhoneBurstification.PhoneBurstification(PhoneBurstification.PhoneBuffType.SendSMS, CallInfoNode)
For Each item As SendBuffnode In li
If SerialPort1.IsOpen Then
G_SendBuffnode = item
SendData = publicMode.StringToByte(item.SendData)
SerialPort1.Write(SendData, 0, SendData.Length)
SendBuffnode.SetSendStatus(item, SendBuffnode.SendStatustype.Sending)
gLogNode = New LogNode($"TX:{item.SendData}", RuningLog.LogType.e_info, RuningLog.LogMode.e_both)
G_Log.AddLogNode(gLogNode)
Else
gLogNode = New LogNode("串口未打开!!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_both)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
While True
If G_SendBuffnode.IsNodeReceiveTimeout2(G_SendBuffnode) Then
If G_SendBuffnode.ReceiveStatus = True Then
If G_SendBuffnode.CommandType = comdType.comdmsg Then
Thread.Sleep(100)
Else
Thread.Sleep(100)
End If
Exit While
'Select Case G_SendBuffnode.CommandType
' Case comdType.comdCDTAM
' If G_SendBuffnode.ReceiveResult = True Then
' Exit While
' End If
' Case comdType.comdCMGF
' Exit While
' Case comdType.comdCSCA
'End Select
End If
Else
gLogNode = New LogNode($"发送超时命令:{item.SendData}", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
End While
Next
Return True
End Function
'拨打电话
Public Sub CallPhone(callLi As List(Of CallInfoNode))
'遍历callli
Dim gLogNode As LogNode
For Each item In callLi
'获取当前时间的utc秒值
Dim nowt As Double = CInt(DateTime.UtcNow.Subtract(New DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds)
'判断是否超时
If item.DeadLine < nowt Then
Continue For
End If
gLogNode = New LogNode($"开始执行{item.CallerName}播打电话:{item.PhoneNumber}", RuningLog.LogType.e_info, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
If ProcessData(item) Then
RedisPublishMessage($"执行{item.CallerName}播打电话:{item.PhoneNumber}成功")
gLogNode = New LogNode($"执行{item.CallerName}播打电话:{item.PhoneNumber}成功", RuningLog.LogType.e_info, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
Else
RedisPublishMessage($"执行{item.CallerName}播打电话:{item.PhoneNumber}失败")
gLogNode = New LogNode($"执行{item.CallerName}播打电话:{item.PhoneNumber}失败", RuningLog.LogType.e_Error, RuningLog.LogMode.e_consoleandRichTextBox)
G_Log.AddLogNode(gLogNode)
End If
Next
End Sub
Public Function ProcessData(CallInfoNode As CallInfoNode) As Boolean
Dim li As List(Of SendBuffnode)
Dim gLogNode As LogNode
Dim SendData As Byte()
li = PhoneBurstification.PhoneBurstification(PhoneBurstification.PhoneBuffType.CallPhoneAndPlay, CallInfoNode)
For Each item As SendBuffnode In li
'If item.CommandType <> comdType.comd1A Then Continue For
'判断串口是否打开
If SerialPort1.IsOpen Then
G_SendBuffnode = item
SendData = publicMode.StringToByte(item.SendData)
SerialPort1.Write(SendData, 0, SendData.Length)
SendBuffnode.SetSendStatus(item, SendBuffnode.SendStatustype.Sending)
gLogNode = New LogNode($"TX:{item.SendData}", RuningLog.LogType.e_info, RuningLog.LogMode.e_both)
G_Log.AddLogNode(gLogNode)
Else
gLogNode = New LogNode("串口未打开!!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_both)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
While True
If G_SendBuffnode.IsNodeReceiveTimeout(G_SendBuffnode) Then
If G_SendBuffnode.ReceiveStatus = True Then
Select Case G_SendBuffnode.CommandType
Case comdType.comdCallPhone
If G_SendBuffnode.ReceiveResult = True Then
Thread.Sleep(1000)
Exit While
Else
gLogNode = New LogNode($"电话已经挂断!!!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
Case comdType.comdSendSMS
Exit While
Case comdType.comdCallPhoneAndPlay
If G_SendBuffnode.ReceiveResult = True Then
If G_SendBuffnode.SendCurrentCount >= 10 Then
SendData = publicMode.StringToByte("AT+CHUP" & vbCrLf)
SerialPort1.Write(SendData, 0, SendData.Length)
gLogNode = New LogNode("主动挂掉电话!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
Else
Thread.Sleep(5000)
If SerialPort1.IsOpen Then
SerialPort1.Write(SendData, 0, SendData.Length)
SendBuffnode.SetSendStatus(item, SendBuffnode.SendStatustype.Resend)
gLogNode = New LogNode($"TX:{item.SendData}", RuningLog.LogType.e_info, RuningLog.LogMode.e_fileandRichTextBox)
G_Log.AddLogNode(gLogNode)
Else
gLogNode = New LogNode("串口未打开!!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
End If
Else
If G_SendBuffnode.CommandType = comdType.comdCallPhoneAndPlay AndAlso Not G_SendBuffnode.ReceiveData.Contains("VOICE CALL: END") Then
Continue While
End If
gLogNode = New LogNode($"电话已经挂断,停止发送语音!!", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
Case Else
Thread.Sleep(50)
Exit While
End Select
End If
Else
gLogNode = New LogNode($"发送超时命令:{item.SendData}", RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return False
End If
'判断接收状态
Thread.Sleep(10)
End While
Next
Return True
End Function
'获取系统缓存参数
Public Sub GetSeting()
'刷新系统缓存
My.Settings.Reload()
'获取系统缓存参数
ComboBox1.Text = My.Settings.SerialPortName
ComboBox2.Text = My.Settings.BaudRate
If My.Settings.THigh = 0 OrElse My.Settings.TWide = 0 Then
Else
Me.Height = My.Settings.THigh
Me.Width = My.Settings.TWide
End If
G_Subscribe = My.Settings.G_Subscribe
G_Publish = My.Settings.G_Publish
ToolStripTextBox2.Text = G_Subscribe
ToolStripTextBox1.Text = G_Publish
Dim dic As Dictionary(Of Integer, (String, String, String))
dic = JsonConvert.DeserializeObject(Of Dictionary(Of Integer, (String, String, String)))(My.Settings.GTable)
If IsNothing(dic) OrElse dic.Count = 0 Then Return
'JsonConvert.SerializeObject(m_Applicationconfig)
End Sub
'保存系统缓存参数
Public Sub SaveSeting()
'刷新系统缓存
My.Settings.Reload()
'获取系统缓存参数
My.Settings.SerialPortName = ComboBox1.Text
My.Settings.BaudRate = ComboBox2.Text
My.Settings.THigh = Me.Height
My.Settings.TWide = Me.Width
My.Settings.G_Subscribe = G_Subscribe
My.Settings.G_Publish = G_Publish
Dim dic As New Dictionary(Of Integer, (String, String, String))
My.Settings.GTable = JsonConvert.SerializeObject(dic)
My.Settings.Save()
End Sub
Private Sub ComboBox1_DropDown(sender As Object, e As EventArgs) Handles ComboBox1.DropDown
'判断串口是否打开
If SerialPort1.IsOpen Then
ComboBox1.DroppedDown = False
MsgBox("串口已打开,请先关闭串口")
'终止下拉
'收起ComboBox1 下拉
Return
End If
ComboBox1.Items.Clear()
ComboBox1.Items.AddRange(SerialPort.GetPortNames())
End Sub
Private Sub ComboBox2_DropDown(sender As Object, e As EventArgs) Handles ComboBox2.DropDown '判断串口是否打开
If SerialPort1.IsOpen Then
MsgBox("串口已打开,请先关闭串口")
Return
End If
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
G_Hexflg = CheckBox1.Checked
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Button1.Text = "打开串口" Then
Try
SerialPort1.PortName = ComboBox1.Text
SerialPort1.BaudRate = CInt(ComboBox2.Text)
SerialPort1.Open()
Button1.Text = "关闭串口"
Button1.ForeColor = Color.Red
Catch ex As Exception
MsgBox("串口打开失败")
End Try
Else
SerialPort1.Close()
Button1.Text = "打开串口"
Button1.ForeColor = Color.Black
End If
End Sub
'使用串口发送数据
Public Function SerialPortSendData(nstr As String, Optional hexflg As Boolean = False) As Boolean
If SerialPort1.IsOpen Then
'判断数据是否为空
If String.IsNullOrEmpty(nstr) Then
MsgBox("发送数据不能为空")
Return False
End If
If hexflg Then
Dim hex As String = StrToHex(nstr)
'RuningLog.OutputLogsToTheControl(RichTextBox1, New RuningLogConfig($"串口发送: {hex}", Color.Green, 12), 1)
SerialPort1.Write(hex)
Else
nstr = nstr & vbCrLf
'RuningLog.OutputLogsToTheControl(RichTextBox1, New RuningLogConfig($"串口发送: {nstr}", Color.Green, 12), 1)
SerialPort1.Write(nstr)
End If
Return True
Else
MsgBox("串口未打开")
Return False
End If
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If SerialPort1.IsOpen Then
SerialPortSendDataTextBox2.Text, G_Hexflg)
Else
MsgBox("串口未打开")
End If
End Sub
'将字符串转Hex 数据
Private Function StrToHex(ByVal str As String) As String
Dim hex As String = ""
For Each c As Char In str
hex += Convert.ToString(Asc(c), 16).PadLeft(2, "0"c) & " "
Next
Return hex
End Function
'将Hex 数据转字符串
Private Function HexToStr(ByVal hex As String) As String
Dim str As String = ""
Dim hexs() As String = hex.Split(" "c)
For Each h As String In hexs
If h <> "" Then
str += ChrW(Convert.ToInt32(h, 16))
End If
Next
Return str
End Function
Private Sub Telephone_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
SaveSeting()
RedisClose()
If Not IsNothingM_EventThread AndAlso M_EventThread.IsAlive Then
M_EventThread.Abort()
End If
If Not IsNothingG_Log Then
G_Log.CloseThread()
End If
End Sub
Private Sub ToolStripButton3_Click(sender As Object, e As EventArgs) Handles ToolStripButton3.Click
RichTextBox1.Clear()
End Sub
Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged
If RichTextBox1.Lines.Length > 2147000000 Then
RichTextBox1.Clear()
End If
End Sub
Private Sub ToolStripButton4_Click(sender As Object, e As EventArgs) Handles ToolStripButton4.Click
If String.IsNullOrEmpty(ToolStripTextBox2.Text) Then
MsgBox("请输入订阅频道")
Return
Else
G_OldSubscribe = G_Subscribe
G_Subscribe = ToolStripTextBox2.Text.Trim
End If
If String.IsNullOrEmpty(ToolStripTextBox1.Text) Then
MsgBox("请输入发布频道")
Return
Else
G_Publish = ToolStripTextBox1.Text.Trim
End If
initRedisSubscriber(G_Subscribe, G_OldSubscribe)
initRedisPublisher()
End Sub
'订阅初始化
''' <summary>
'''
''' </summary>
''' <param name="Subscribe"></param>
''' <param name="OldSubscribe"></param>
Public Sub initRedisSubscriber(Subscribe As String, OldSubscribe As String)
If String.IsNullOrEmpty(Subscribe) Then
MsgBox("未设置订阅频道")
Return
End If
If Not IsNothing(G_RedisSub) AndAlso G_RedisSub.IsConnected Then
' 取消订阅并关闭连接
G_RedisSub.UnsubscribeFromChannel(OldSubscribe)
G_RedisSub.CloseConnection()
End If
' 替换为你的 Redis 连接字符串
Dim connectionString = "127.0.0.1:6379"
Try
G_RedisSub = New RedisSubscriber(connectionString)
' 定义消息处理程序
Dim messageHandler As Action(Of RedisChannel, RedisValue) = Sub(channel, message)
Dim gLogNode As LogNode
Dim g_CallInfoNode As CallInfoNode
Try
g_CallInfoNode = JsonConvert.DeserializeObject(Of CallInfoNode)(message)
Catch ex As Exception
'MsgBox($"消息解析失败:{ex.Message}")
gLogNode = New LogNode(ex.Message, RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
Return
End Try
gLogNode = New LogNode($"Redis:{channel}: {message}", RuningLog.LogType.e_info, RuningLog.LogMode.e_fileandRichTextBox)
G_Log.AddLogNode(gLogNode)
M_RedisQueue.Enqueue(g_CallInfoNode)
'Console.WriteLine($"接收到来自 {channel} 的消息: {message}")
End Sub
' 订阅频道
G_RedisSub.SubscribeToChannel(Subscribe, messageHandler)
Catch ex As Exception
MsgBox($"订阅失败:{ex.Message}")
End Try
'' 发布消息示例
'Console.WriteLine("发布测试消息...")
'G_RedisSub.PublishMessage("testChannel", "Hello from publisher!")
'' 保持程序运行以接收更多消息
'Console.WriteLine("按任意键退出...")
'Console.ReadKey()
End Sub
Private Sub ToolStripButton5_Click(sender As Object, e As EventArgs) Handles ToolStripButton5.Click
RedisPublishMessage("20131415926")
End Sub
'redis发布初始化
Public Sub initRedisPublisher()
If Not IsNothing(G_Redislish) AndAlso G_Redislish.IsConnected Then
G_Redislish.CloseConnection()
End If
' 替换为你的 Redis 连接字符串
Dim connectionString = "127.0.0.1:6379"
Try
G_Redislish = New RedisSubscriber(connectionString)
Catch ex As Exception
MsgBox($"redis发布初始化失败:{ex.Message}")
End Try
End Sub
'发布消息
Public Sub RedisPublishMessage(message As String)
If String.IsNullOrEmpty(G_Publish) Then
MsgBox("未设置发布频道")
Return
End If
If String.IsNullOrEmpty(message) Then
MsgBox("未输入发布内容")
Return
End If
If G_Redislish.IsConnected Then
Dim gLogNode As LogNode
Try
G_Redislish.PublishMessage(G_Publish, message)
gLogNode = New LogNode($"Redis:{G_Publish}: {message}", RuningLog.LogType.e_info, RuningLog.LogMode.e_fileandRichTextBox)
G_Log.AddLogNode(gLogNode)
Catch ex As Exception
MsgBox($"redis发布失败:{ex.Message}")
gLogNode = New LogNode(ex.Message, RuningLog.LogType.e_Error, RuningLog.LogMode.e_fileandRichTextBox)
gLogNode.SetLogColor(Color.Red)
G_Log.AddLogNode(gLogNode)
End Try
Else
MsgBox("redis未连接")
End If
End Sub
Public IsRead As Boolean = False
Public listening As Boolean = False
Public recvBufferli As List(Of Byte)
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'获取读缓冲区数据长度
Dim gLogNode As LogNode
Dim n As Integer = SerialPort1.BytesToRead
Dim recvBuffer As Byte() = New Byte(n - 1) {}
SerialPort1.Read(recvBuffer, 0, n)
If Not IsNothing(G_SendBuffnode) Then
G_SendBuffnode.ReceiveStatusStateMachine(G_SendBuffnode, recvBuffer)
'SendBuffnode.SetSendStatus(G_SendBuffnode, SendBuffnode.SendStatustype.ReceiveSuccess)
End If
'输出到富文本
If G_Hexflg Then
'RuningLog.OutputLogsToTheControl(RichTextBox1, New RuningLogConfig($"串口接收到数据:{ByteToString2(recvBuffer)}", Color.Olive, 12), 1)
gLogNode = New LogNode($"RX{ByteToString2(recvBuffer)}", RuningLog.LogType.e_info, RuningLog.LogMode.e_fileandRichTextBox)
G_Log.AddLogNode(gLogNode)
Else
'RuningLog.OutputLogsToTheControl(RichTextBox1, New RuningLogConfig($"串口接收到数据:{Encoding.Default.GetString(recvBuffer)}", Color.Olive, 12), 1)
gLogNode = New LogNode($"RX{Encoding.Default.GetString(recvBuffer)}", RuningLog.LogType.e_info, RuningLog.LogMode.e_fileandRichTextBox)
G_Log.AddLogNode(gLogNode)
End If
'Dim readstr As String = publicMode.ByteToString(recvBuffer)
End Sub
Public Shared Function ByteToString2(databuff() As Byte)
Dim strData As String = String.Empty
For i = 0 To databuff.Length - 1
strData &= $" {ByteToHex1(databuff(i)).PadLeft(2, "0"c)}"
Next
Return strData
End Function
Public Shared Function ByteToHex1(ByVal b As Byte) As String
Return b.ToString("X2")
End Function
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
'TextBox1
'判断TextBox1 是否为空
If String.IsNullOrEmpty(TextBox1.Text) Then
MsgBox("电话号码为空")
Return
End If
'判断TextBox1 是否为数字 且符合电话号码格式
If Not IsNumeric(TextBox1.Text) OrElse TextBox1.Text.Length <> 11 Then
MsgBox("电话号码格式不正确")
Return
End If
Dim str As String = $"ATD{TextBox1.Text};"
SerialPortSendDatastr, False)
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Console.WriteLine(publicMode.SwapAndPad("18144070918"))
End Sub
'关闭redis
Public Sub RedisClose()
If Not IsNothing(G_RedisSub) AndAlso G_RedisSub.IsConnected Then
G_RedisSub.UnsubscribeFromChannel(G_Subscribe)
G_RedisSub.CloseConnection()
End If
If Not IsNothing(G_Redislish) AndAlso G_Redislish.IsConnected Then
G_Redislish.CloseConnection()
End If
End Sub
End Class