电脑和手机通讯(二)

来源:互联网 发布:迅龙数据恢复教程 编辑:程序博客网 时间:2024/04/30 01:27

 

上一次解决了PDU编码的解码问题。这次就来写从串口中读取数据。

与串口通讯,在net里面提供了十分方便的控件和类库,如果你要简单的话,可以从工具栏里拖出serialport 这个控件,使用控件的好处在于,当有数据回传的时候,会触发控件的一个方法,我们在该方法下进行操作,就可以省去自己再写一个方法去试探有没有从串口来的数据了。不过,经过我测试,觉得还是要自己写比较好。

首先,我们要定义个读写串口的类

Dim ser as new system.io.ports.serialport

然后让设置一下这个类的一些属性,如串口名称

Ser.portname="COM3"

接着就打开串口

Ser.open()

接着就往串口里写命令

Ser.writeline("命令")

再接着就是自己写一个判断,判断是否有数据从串口里过来,如果有则执行读数据

ser.ReadLine()

接着就是把这个读取的一行数据进行判断,如果是pdu码则去进行解码,如果是结束符号则结束,如果是错误符号就去执行其他操作。

接着就是又回到上面的判断有没有第二行数据,然后就循环到没东西为止。

 

思路大概就是这样子,然后把成功读出的内容显示到程序界面的listview中,并把它存到数据库中。

整个程序功能简单,设计也不复杂,实现起来大概200行不到。以下是我做的程序的一些介绍。我使用了:

一个combobox 作为选择COM之用,

一个button,用来连接和断开串口;

一个button,用来开始和停止监听是否有短信到达;

一个listview,用来显示数据;

一个timer,用来定时向串口发送检查信息,检查是否有新短信到达;

一个timer,用来读取串口发来的消息,直到没有消息了就停止。

界面就是这样子。还用到了一个access数据库,里面有一个表(msm)用来记录短信信息。

程序初始化时,先找出所有的com口,赋值给combobox,并检查数据库文件是否存在

 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Button2.Enabled = False

        Dim arrport As String() = IO.Ports.SerialPort.GetPortNames

        ComboBox1.Items.AddRange(arrport)

        ComboBox1.SelectedIndex = 0

        Dim aaa As New db

End Sub

 

接着,当单击连接按钮时,就与串口连接

 

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        If ComboBox1.SelectedItem.ToString = "" Then Exit Sub

        If Button1.Text = "连接" Then

            ser.PortName = ComboBox1.SelectedItem.ToString

            ser.Open()

            Button1.Text = "关闭"

            Button2.Enabled = True

        ElseIf Button1.Text = "关闭" Then

            Timer1.Enabled = False

            Timer2.Enabled = False

            ser.Close()

            Button1.Text = "连接"

            Button2.Text = "监听新短信"

            Button2.Enabled = False

        End If

    End Sub

 

如果链接成功,则可以点击开始监听按钮,该按钮主要是让timer1启动,timer1的主要功能就是定时的向串口发送请求,询问是否有新短信的到达。

 

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        If Button2.Text = "监听新短信" Then

            Timer1.Enabled = True

            Button2.Text = "停止监听"

        ElseIf Button2.Text = "停止监听" Then

            Timer1.Enabled = False

            Timer2.Enabled = False

            Button2.Text = "监听新短信"

        End If

    End Sub    

 

 

 

Timer1 的工作很简单,就是向串口发送一个信息,并启动timer2继续工作。

 

Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        ser.WriteLine(mess)

        Timer1.Enabled = False

        Timer2.Enabled = True

End Sub

 

 

Timer2 的工作就多点,它首先是判断串口接收缓冲区里面有没有数据,如果没有则过,如果有则读取一行数据,并进行判断,如果是结束符就结束,如果是pdu码则进行处理。

 

Private Sub Timer2_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer2.Tick

        Dim i As Integer = ser.BytesToRead

        If i = 0 Then Exit Sub

        Dim strtemp As String = ser.ReadLine

        Dim iii As Integer = strtemp.Length

        If strtemp = vbCr Then '空行

            '不处理

        ElseIf Trim(strtemp) = mess Then '是发送出去的字符集

            '不处理

        ElseIf Trim(strtemp) = "OK" + vbCr Then '是结束行

            '结束这个timer2,启动timer1继续监听

            Timer2.Enabled = False

            Timer1.Enabled = True

        ElseIf strtemp.StartsWith("+CMGL") Then '是信息摘要行

            '不处理

        ElseIf Trim(strtemp) = "ERROR" + vbCr Then  '是错误

            '结束这个timer,发送错误信息

            Timer2.Enabled = False

            Timer1.Enabled = True

        Else  '是pdu码

            '发去解码

            Dim jieguo As String() = chuli(strtemp)

            addlist(jieguo)

 

        End If

    End Sub

 

整个过程大概就是如此了。

下面就不多说了,认真看一下就明了。

 

Sub addlist(ByVal data() As String) '执行添加

        Dim myitem As New ListViewItem

        myitem.Text = data(0)        '手机号码

        Dim mysubitem(2) As ListViewItem.ListViewSubItem

        mysubitem(0) = New ListViewItem.ListViewSubItem()

        mysubitem(1) = New ListViewItem.ListViewSubItem()

        mysubitem(2) = New ListViewItem.ListViewSubItem()

 

        mysubitem(0).Text = data(1)  '内容

        mysubitem(1).Text = data(2) '短信中心码

        mysubitem(2).Text = data(3) '时间

        myitem.SubItems.AddRange(mysubitem)

        ListView1.Items.Add(myitem)

        Dim mycl As New db

        mycl.insertduanxin(data(0), data(1), data(2), data(3))

    End Sub

 

 

下面的就是上一次说的pdu解码函数了,只是粗略的改了几行而已:

 

Function chuli(ByVal data As String) As String()                       '处理pdu码的函数

        Dim seek As Integer = 0

        Dim sclength As Integer = CType(data.Substring(0, 2), Integer)   '手机中心码长度

        Dim zhongxinma As String = data.Substring(seek + 2, sclength * 2) '手机中心码的pdu码

        zhongxinma = number(zhongxinma.Substring(2))      '解码后的手机中心码

        seek = sclength * 2 + seek + 2                   '指针移动

        Dim weizhi As String = data.Substring(seek, 2)   '读取下一个参数,未知的参数

        seek += 2                                        '指针继续移动

        Dim haomalength As Double = Val("&H" + data.Substring(seek, 2)) / 2 '手机号码长度

        seek += 2

        haomalength = Math.Ceiling(haomalength)

        Dim haoma As String

        haoma = number(data.Substring(seek + 2, haomalength * 2)) '解码后的手机号码

        seek = seek + 2 + haomalength * 2

        Dim weizhi2 As String = data.Substring(seek + 1, 2)   '未知参数

        seek += 2

        Dim putong As String = data.Substring(seek, 2) '如果为08则为普通短信

        seek += 2

        Dim time As String = times(number(data.Substring(seek, 14)))   '日期

        seek += 14

        Dim contentlength As Double = Val("&H" + data.Substring(seek, 2)) / 2  '内容有多少个字符

        Dim neirong As String = content(data.Substring(seek + 2, contentlength * 4))  '获取解码后的内容

        Dim jieguo(3) As String

        jieguo(0) = haoma

        jieguo(1) = neirong

        jieguo(2) = zhongxinma

        jieguo(3) = time

        Return jieguo

    End Function

 

 

 

    Function number(ByVal data As String) As String     '号码解码

        Dim str As String = ""

        For i As Integer = 0 To data.Length / 2 - 1

            str += Strings.StrReverse(data.Substring(i * 2, 2))

        Next

        str = str.Replace("F", "")

        Return str

    End Function

 

 

    Function content(ByVal data As String) As String   '内容解码

        Dim str As String = ""

        For i As Integer = 0 To data.Length / 4 - 1

            Dim temp As String = "&H" + data.Substring(i * 4, 4)

            Dim word As Char = ChrW(CType(Val(temp), Integer))

            str += word

        Next

        Return str

    End Function

 

 

    Function times(ByVal data As String) As String   '时间解码

        Dim yy, mm, dd, hh, ff, ss, riqi As String

        yy = data.Substring(0, 2)

        mm = data.Substring(2, 2)

        dd = data.Substring(4, 2)

        hh = data.Substring(6, 2)

        ff = data.Substring(8, 2)

        ss = data.Substring(10, 4)

        riqi = mm + "/" + dd + " " + hh + ":" + ff

        Return riqi

    End Function

 

 

下面的就是写入数据库的db类:

Imports System.Data.OleDb

 

Public Class db

    Dim cmdstr As String

    Dim cmd As New OleDb.OleDbCommand

    Public connstr As String

    Dim conn As New OleDb.OleDbConnection(connstr)

    Dim dbadd As String = "db.mdb"            'access名称

    Sub New()

        Dim mypath As String = My.Application.Info.DirectoryPath

        If IO.File.Exists(mypath + "/" + dbadd) Then

            connstr = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Persist Security Info=False", mypath + "/" + dbadd)

        Else

            Throw New Exception("在程序的同目录下找不到数据库" + dbadd)

 

        End If

    End Sub

    Function execno() As Boolean

        cmd.CommandText = cmdstr

        cmd.Connection = conn

        conn.ConnectionString = connstr

        conn.Open()

        Dim i As Integer = cmd.ExecuteNonQuery()

        If i = 1 Then Return True

    End Function

 

    Function insertduanxin(ByVal haoma As String, ByVal content As String, ByVal zhongxinma As String, ByVal riqi As String) As Boolean

        cmdstr = "insert into msm(haoma,content,zhongxinma,riqi) values(@haoma,@content,@zhongxinma,@riqi) "

        cmd.Parameters.Add("@haoma", OleDbType.Char).Value = haoma

        cmd.Parameters.Add("@content", OleDbType.Char).Value = content

        cmd.Parameters.Add("@zhongxinma", OleDbType.Char).Value = zhongxinma

        cmd.Parameters.Add("@riqi", OleDbType.Char).Value = riqi

        execno()

    End Function

 

End Class

 

 

注:如果你照抄一定错,因为有几个变量是没有写出来的,不过细心的你一定看的出来。

至此,一个能够读取出手机新短信的程序就完成了。经过测试,正常。