PDA Battery Info (VB.Net+.Net CF) Source Code

PDA Battery Info (VB.Net+.Net CF) Source Code

'======================================
' Get PDA Battery Info
'Summary:
' Using P/Invoke to get Battery Info.
'This technique is introduced in MSDN
'Library - January 2005 and this program
'is written based on the sample program
'of ms-help://MS.MSDNQTR.2005JAN.1033/dncfhowto/html/getpowstat.htm
'Functions:
' This program get PDA's battery info-
'mation containing main battery lifetime,
'voltage,current,and backup battery info.
'
'2005/3/17
'Hesicong
'http://dream-world.nease.net
'http://blog.csdn.net/hesicong
'mailto:hesicong@mail.sc.cninfo.net
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.Windows.Forms
Imports System.Data
Imports System.Runtime.InteropServices
' Summary description for Form1.
Public Class BatteryInfo
Inherits System.Windows.Forms.Form
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Private mainMenu1 As System.Windows.Forms.MainMenu
Public Sub New()
'
' Required for Windows Form Designer support
'
InitializeComponent()
End Sub 'New
'
' TODO: Add any constructor code after InitializeComponent call
'
' Clean up any resources being used.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
End Sub 'Dispose
#Region "Windows Form Designer generated code"
' Required method for Designer support - do not modify
' the contents of this method with the code editor.
Friend WithEvents MenuItem4 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem5 As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem7 As System.Windows.Forms.MenuItem
Friend WithEvents Timer1 As System.Windows.Forms.Timer
Friend WithEvents mnuAutoRefresh As System.Windows.Forms.MenuItem
Friend WithEvents mnuAbout As System.Windows.Forms.MenuItem
Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
Private Sub InitializeComponent()
Me.mainMenu1 = New System.Windows.Forms.MainMenu
Me.MenuItem4 = New System.Windows.Forms.MenuItem
Me.MenuItem5 = New System.Windows.Forms.MenuItem
Me.mnuAutoRefresh = New System.Windows.Forms.MenuItem
Me.MenuItem7 = New System.Windows.Forms.MenuItem
Me.mnuAbout = New System.Windows.Forms.MenuItem
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.Timer1 = New System.Windows.Forms.Timer
Me.MenuItem1 = New System.Windows.Forms.MenuItem
'
'mainMenu1
'
Me.mainMenu1.MenuItems.Add(Me.MenuItem4)
Me.mainMenu1.MenuItems.Add(Me.mnuAbout)
'
'MenuItem4
'
Me.MenuItem4.MenuItems.Add(Me.MenuItem5)
Me.MenuItem4.MenuItems.Add(Me.mnuAutoRefresh)
Me.MenuItem4.MenuItems.Add(Me.MenuItem1)
Me.MenuItem4.MenuItems.Add(Me.MenuItem7)
Me.MenuItem4.Text = "Menu"
'
'MenuItem5
'
Me.MenuItem5.Text = "Refresh"
'
'mnuAutoRefresh
'
Me.mnuAutoRefresh.Text = "AutoRefresh"
'
'MenuItem7
'
Me.MenuItem7.Text = "End"
'
'mnuAbout
'
Me.mnuAbout.Text = "About"
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(8, 8)
Me.TextBox1.Multiline = True
Me.TextBox1.ScrollBars = System.Windows.Forms.ScrollBars.Horizontal
Me.TextBox1.Size = New System.Drawing.Size(224, 256)
Me.TextBox1.Text = ""
'
'Timer1
'
Me.Timer1.Interval = 1000
'
'MenuItem1
'
Me.MenuItem1.Text = "SetRefreshInterval"
'
'BatteryInfo
'
Me.Controls.Add(Me.TextBox1)
Me.Menu = Me.mainMenu1
Me.Text = "BatteryInfo"
End Sub 'InitializeComponent
#End Region
' The main entry point for the application.
Shared Sub Main()
Application.Run(New BatteryInfo)
End Sub 'Main
Public Class SYSTEM_POWER_STATUS_EX2
Public ACLineStatus As Byte
Public BatteryFlag As Byte
Public BatteryLifePercent As Byte
Public Reserved1 As Byte
Public BatteryLifeTime As System.UInt32
Public BatteryFullLifeTime As System.UInt32
Public Reserved2 As Byte
Public BackupBatteryFlag As Byte
Public BackupBatteryLifePercent As Byte
Public Reserved3 As Byte
Public BackupBatteryLifeTime As System.UInt32
Public BackupBatteryFullLifeTime As System.UInt32
Public BatteryVoltage As System.UInt32
Public BatteryCurrent As System.UInt32
Public BatteryAverageCurrent As System.UInt32
Public BatteryAverageInterval As System.UInt32
Public BatterymAHourConsumed As System.UInt32
Public BatteryTemperature As System.UInt32
Public BackupBatteryVoltage As System.UInt32
Public BatteryChemistry As Byte
End Class 'SYSTEM_POWER_STATUS_EX2

Public Class SYSTEM_POWER_STATUS_EX
Public ACLineStatus As Byte
Public BatteryFlag As Byte
Public BatteryLifePercent As Byte
Public Reserved1 As Byte
Public BatteryLifeTime As System.UInt32
Public BatteryFullLifeTime As System.UInt32
Public Reserved2 As Byte
Public BackupBatteryFlag As Byte
Public BackupBatteryLifePercent As Byte
Public Reserved3 As Byte
Public BackupBatteryLifeTime As System.UInt32
Public BackupBatteryFullLifeTime As System.UInt32
End Class 'SYSTEM_POWER_STATUS_EX
<DllImport("coredll")> _
Private Shared Function GetSystemPowerStatusEx(ByVal lpSystemPowerStatus As SYSTEM_POWER_STATUS_EX, ByVal fUpdate As Boolean) As System.UInt32
End Function
<DllImport("coredll")> _
Private Shared Function GetSystemPowerStatusEx2(ByVal lpSystemPowerStatus As SYSTEM_POWER_STATUS_EX2, ByVal dwLen As System.UInt32, ByVal fUpdate As Boolean) As System.UInt32
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
RefreshStatus()
End Sub 'Form1_Load
Private Sub RefreshStatus()
Dim status As New SYSTEM_POWER_STATUS_EX
Dim status2 As New SYSTEM_POWER_STATUS_EX2
TextBox1.Text = ""
TextBox1.Text = "Sample Time:" & Format(Now, "HH:mm:ss") + vbCrLf + vbCrLf
With TextBox1
If Convert.ToInt32(GetSystemPowerStatusEx(status, False)) = 1 Then
'Do some further work here
End If
If Convert.ToInt32(GetSystemPowerStatusEx2(status2, Convert.ToUInt32(Marshal.SizeOf(status2)), False)) = Marshal.SizeOf(status2) Then
Select Case CInt(status2.ACLineStatus.ToString)
Case 0
.Text += "AC Status: Offline" + vbCrLf
Case 1
.Text += "AC Status: Online" + vbCrLf
Case Else
.Text += "AC Status: Unknown" + vbCrLf
End Select
.Text += vbCrLf
.Text += "MainBattery" + vbCrLf
.Text += "-LifePercent:" & status2.BatteryLifePercent.ToString + vbCrLf
.Text += "-Voltage:" & (CInt(status2.BatteryVoltage.ToString) / 1000).ToString + "V" + vbCrLf
.Text += "-Current:" & status2.BatteryCurrent.ToString + "mA" + vbCrLf
.Text += "-Temperature:" & (CInt(status2.BatteryTemperature.ToString) / 10).ToString + "℃" + vbCrLf
.Text += vbCrLf
.Text += "BackupBattery" + vbCrLf
.Text += "-LifePercent:" & status2.BackupBatteryLifePercent.ToString + vbCrLf
.Text += "-Voltage:" & (CInt(status2.BackupBatteryVoltage.ToString) / 1000).ToString + "V" + vbCrLf
End If
End With
End Sub
Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Application.Exit()
End Sub
Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
RefreshStatus()
End Sub
Private Sub MenuItem7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem7.Click
Application.Exit()
End Sub
Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem5.Click
RefreshStatus()
End Sub
Private Sub mnuAutoRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuAutoRefresh.Click
mnuAutoRefresh.Checked = Not (mnuAutoRefresh.Checked)
Timer1.Enabled = mnuAutoRefresh.Checked
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
RefreshStatus()
End Sub
Private Sub mnuAbout_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuAbout.Click
MsgBox("Program by Hesicong" & vbCrLf & "http://dream-world.nease.net" & vbCrLf & " http://blog.csdn.net/hesicong" & vbCrLf & "QQ:38288890", MsgBoxStyle.OKOnly, "About")
End Sub
Private Sub MenuItem1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click
Timer1.Interval = CInt(InputBox("Please enter autorefresh interval(s)", "BatteryInfo", "1")) * 1000
End Sub

End Class 'Form1

恭喜六级通过!

今天凌晨查询了6级成绩,66分,过了!女友也过了,很高兴。庆祝庆祝!

.net平台手机管理软件开发 暂时告一段落

整个寒假完成了我预想的1-12,基本上达到了讲解基本知识的目的。马上就要上学了,所以正在准备上学的事情了。下学期的任务比较重,我会抽空把相关开发经验写出来的。希望大家继续关注。

.net平台手机管理软件开发(12)—— 短信部分 通过RS232发送和接收短信

(十二) **短信部分——通过RS232**发送和接收短信

通常,发送和接收短信的终端都是通过串行接口连接电脑,这类设备用得比较多的是GSM Modem和手机。这类设备通常都支持PDU模式,但仍有少数设备只支持Text模式。

设备硬件连接好以后可以通过发送AT指令测试设备是否连接正确能否正常通讯。在这里我使用Windows自带的“超级终端”工具进行通讯。此工具可以在程序——附件——通讯里面找到,如果没有请确认是否安装了此组件。或者在运行里面输入“hypertrm”也可以快速启动“超级终端”。

以下所有范例均以Siemens M55手机作为终端,有可能跟你设备返回的不同。具体参数清参阅设备相关AT指令集。本手机AT指令集在我主页上有下载。
准备工作:
. 测试连接:“AT8 ”测试终端是否连接正确。成功后返回“OK”。
. 设置回显:(此步骤为了测试方便)ATE18

. 查阅及设置字符集:
AT+CSCS=?8
+CSCS: (“GSM”,”UCS2”)

说明该终端支持GSM与UCS2两种字符集。一般对于中文环境设置为UCS2
AT+CSCS=”UCS2”8

. *取得短信中心号码:
*
AT+CSCA? 8
+CSCA: “+8613800280500”,145

. 查询并设置SMS**格式:
**查询:AT+CMGF= 8
返回:+CMGF: (0)
0代表PDU模式。你的设备可能有其他的选项,请参考设备的AT指令集。

设置:AT+CMGF=08

. 查询并设置短信储存位置:
查询:AT+CPMS=?8
返回:+CPMS: (“MT”,”SM”,”ME”),(“MT”,”SM”,”ME”),(“MT”,”SM”,”ME”)

其中MT表示设备所有可用储存位置。SM代表SIM卡,ME代表机身。

一般设置为:AT+CPMS= “MT”,”MT”,”MT”8
查询短信:

. 查询具有相同状态的所有短信
**
指令**:AT+CMGL=n

其中n代表0-4的数字。
0——未读得短信。执行命令以后自行变为已读取。
1——已读短信。
2——草稿。
3——已发送短信。
4——全部
*返回(例):
*
+CMGL: 76,3,,20

0891683108200805F011620D91683194041338F50000FF0530972D8603
76——序号
3——状态:发送
20——PDU串长度

. 查询特定序号的短信
**
指令**:AT+CMGR=n8

其中n代表序号
返回(例):
+CMGR: 3,,20
0891683108200805F011620D91683195041338F50000FF0530972D8603
3——状态:发送
20——PDU串长度
注意:PDU**串长度表示PDU中除去短信中心部分剩下的代码的长度的1/2。例如上述PDU中PDU长度部分为11620D91683195041338F50000FF0530972D8603,40个字符,表示20**个字节。


储存PDU
**
指令**:
AT+CMGW=[PDU长度] 8

[PDU串]
例如: AT+CMGW=208

0891683108200805F011620D91683195041338F50000FF0530972D8603

注意,输入PDU后按“CTRL+Z”终止。程序中使用0x1A,0x1D作为终止。

返回:+CMGW: 85
85——序号

发送PDU**串**

. 发送输入的PDU串
指令:
AT+CMGS=[PDU长度] 8

[PDU代码]

. 发送指定序号的PDU串
*指令:
*
AT+CMSS=[序号] 8

接收短信

接收刚收到的短信有两种方法:轮询终端;使用事件

轮询终端可以定期的使用AT+CMGL=0指令读取未读取得指令。方法简单,但许多时候都在做无用功,效率低下,一般不建议采用。下面主要讲解事件法:

*指令:
*
AT+CNMI=,,,,

参数:
mode**
:** ** 0**——缓存在终端
1**——直接发送到TE
mt
:** ** 0**——接收到新的SMS不返回事件

** 1**——如果接收到的SMS存储在ME,则返回
+CMTI:,

** 2**——除了Class2 SMS,新的SMS直接发送到终端,返回:
+CMT:
3**——Class3 SMS使用mt=2的方法返回,其他类型的使用mt=1的方法返回。
bm
:** ** 0**——小区广播不通知

** 2**——新的小区广播通知,返回
+CBM:
3**——Class3格式的小区广播通知,使用bm=2格式
ds
:** ** 0**——状态报告不通知

** 1**——新的状态报告通知,返回:
+CDS:
2**——如果新的状态报告存储到ME,则返回:
+CDSI:,
brf
:** ** 1**——始终为1
例:

一般我们使用AT+CNMI=1,1,0,2,1

当收到新的短信时终端返回:
+CMTI:ME,5

新的状态报告:
+CDSI:ME,6

程序可以通过判断返回值并使用AT+CMGR指令返回新到短信。

.net平台手机管理软件开发(11)—— 短信部分 VB.NET编码PDU

(十一) **短信部分——VB.NET**编码PDU
PDU的编码器的工作原理是解码器的逆过程。根据需要编码器只需要编码发送的PDU代码,工作相对简单。本文讲解编码思路,具体代码请参考Blog中PDUEncoder部分

我把PDU的编码分为两部分,SMS和EMS。EMS部分我只提供了ConcatenatedShortMessage的编码器。这是超长短信的编码,用得最多。
SMS**编码**

编码一个SMS一般需要如下的信息:
TP_Data_Coding_Scheme TP_UD编码方式
TP_Destination_Address 对方号码
TP_Message_Reference 参考号码
TP_Status_Report_Request 状态报告
TP_User_Data 用户信息
TP_Validity_Priod 有效期
ServiceCenterNumber 短信中心号码

所以在编码器中存在以上的属性,并在Set中加入了处理代码,将可读信息转换成对应的十六进制信息。

特别注意的是TP_User_Data属性,它可以根据用户数据编码自动设置TP_UDL。对于纯英文编码,TP_UDL为所有的字符数;对于Unicode编码,由于一个字符由两个字节表示,TP_UDL为所有的字符数2。注意检查TP_User_Data的长度,对于SMS来说编码后的TP_UD长度不能超过140字节。也就是说英文160个字符(140/78),中文70个字符。

对于TP_UD的编码在解码器中也有说明,在此不再赘述。

我还设计了几个枚举变量:
ENUM_TP_DCS 编码方式
ENUM_TP_SRI 状态报告
ENUM_TP_VALID_PERIOD 有效期
ENUM_TP_VPF 有效期格式

这些枚举变量可以简化输入,也利于日后扩充。

当以上内容设置好以后,基本上一个短信的架子就出来了。此时调用GetSMSPDUCode进行组合,简单的把十六进制拼接起来就形成了一个完整的PDU代码。
EMS**——ConcatenatedShortMessage**部分

编码EMS较SMS复杂,但每条EMS的基础还是SMS,所以我直接继承了SMS类。区别主要是要处理好TP_UD和IE。对于ConcatenatedShortMessage,由于其IE和TP_UDHL占据了TP_UD的部分空间,所以每条短信英文只能容纳133字符,中文66字符。我们可以通过此信息得到短信条数。

如果TP_DCS为Unicode编码,则短信条目为:
TotalMessages = (TP_UD.Length / 4) 66 + ((TP_UD.Length / 4 Mod 66) = 0)+1

如果为7bit,则为:
TotalMessages = (tp_ud.Length 266) - ((tp_ud.Length Mod 266) = 0)+1

注意在程序中我为了简化以后的数组操作,就没有加一。

确定了短信条数以后通过一个循环就可以提取出每条短信的TP_UD。
Select Case tp_dcs
Case ENUM_TP_DCS.UCS2
tmpTP_UD = Mid(TP_UD, i * 66 * 4 + 1, 66 * 4)’When TP_UDL is odd, the max length of an Unicode string in PDU code is 66 Charactor.See [3GPP TS 23.040 V6.5.0 (2004-09] 9.2.3.24.1
Case ENUM_TP_DCS.DefaultAlphabet
tmpTP_UD = Mid(tp_ud, i * 133 * 2 + 1, 133 * 2)
End Select

此后还需要编码IE部分,关键代码是确定TP_UDL的值。对于TP_DCS为7bit来说确定此值显得比较复杂,弄不好容易出现多一个少一个的错误。
If tp_dcs = ENUM_TP_DCS.UCS2 Then
TP_UDL = tmpTP_UD.Length / 2 + 6 + 1 ‘6: length of IE
End If
If tp_dcs = ENUM_TP_DCS.DefaultAlphabet Then
TP_UDL = Fix((tmpTP_UD.Length + 7 * 2) * 4 / 7) ‘6:length of IE
End If

然后根据3GPP里关于EMS的结构的说明就可以编写出EMS PDU的处理程序。详见原代码。

如果需要扩展EMS以适应更多种类的EMS,可以参考3GPP写出更为强大的编码程序。但最关键的还是需要处理好IE以及TP_UDL。