'==========================================================
' SMS,EMS Decoder
' 2004-9-24
'1.Description
' This class decode a SMS or EMS PDU code to a certain
'class. You can use it in your software to read SMSs and
'EMSs. All of this is done under GSM 03.40. I tested it
'on my SIEMENS M55 and NOKIA 8xxx and it works well.
'2.Useage
' If you know what type of PDU code, you can create a
'new instance of class like DIM s as SMS(myPDUCode)
'When instance is created, you read its public variable
'to get what you want.
' When TP_DCS=0, PDU code is coded from 7bit
'charactor (see GSM 03.38), use shared function
'Deocde7Bit to decode it.
' When TP_DCS=8, PDU code is coded from Unicode
'charactor (see GSM 03.38), use shared funtion
'DecodeUnicode to decode it.
'3.Bugs
' So far in my tests I found none.
'4.When you use it
' You can freely use it or modify it in your program,
'but when you find bugs or improved it please publish it
'or send one copy to me. Thanks
'5.About me
' I am writting a program which can list folders and
'files in SIEMENS M55 mobile phone. It can also read
'and send SMS,EMS. Some documents are hard to find on
'internet, but I keep on my mind to study it and finally
'I found it is full of interests.
' I like freedom, so'I exchange my ideas with all of
'the world. It is so happy that you can use my classes!
' In the end, sorry for my poor english.
'6.Contact me
' Email:hesicong@mail.sc.cninfo.net
' QQ:38288890
' Homepage:http://hesicong2004.vip.myrice.com (Chinese)
' ----By HESICONG
'Last edited 2004-9-24
Public MustInherit Class SMS
Public SCAddressLength As Byte
Public SCAddressType As Byte
Public SCAddressValue As String
Public FirstOctet As Byte
Public TP_PID As Byte
Public TP_DCS As Byte
Public TP_UDL As Byte
Public TP_UD As String
Public Text As String
Public Type As SMSType
Public UserData As String
Public Enum SMSType
SMS_RECEIVED = 0
SMS_STATUS_REPORT = 2
SMS_SUBMIT = 1
EMS_RECEIVED = 64 'It is "Reserved" on my phone??
EMS_SUBMIT = 65
End Enum
Public MustOverride Sub GetOrignalData(ByVal PDUCode As String)
'Get a byte from PDU string
Shared Function GetByte(ByRef PDUCode As String) As Byte
Dim r As Byte = Val("&H" + Mid(PDUCode, 1, 2))
PDUCode = Mid(PDUCode, 3)
Return r
End Function
'Get a string of certain length
Shared Function GetString(ByRef PDUCode As String, ByVal Length As Integer) As String
Dim r As String = Mid(PDUCode, 1, Length)
PDUCode = Mid(PDUCode, Length + 1)
Return r
End Function
'Get date from SCTS format
Shared Function GetDate(ByRef SCTS As String) As Date
Dim year, month, day, hour, minute, second, timezone As Integer
year = Val(Swap(GetString(SCTS, 2))) + 2000
month = Val(Swap(GetString(SCTS, 2)))
day = Val(Swap(GetString(SCTS, 2)))
hour = Val(Swap(GetString(SCTS, 2)))
minute = Val(Swap(GetString(SCTS, 2)))
second = Val(Swap(GetString(SCTS, 2)))
timezone = Val(Swap(GetString(SCTS, 2)))
Dim result As New Date(year, month, day, hour, minute, second)
Return result
End Function
'Swap two bit
Shared Function Swap(ByRef TwoBitStr As String) As String
Dim c() As Char = TwoBitStr.ToCharArray
Dim t As Char
t = c(0)
c(0) = c(1)
c(1) = t
Return (c(0) + c(1)).ToString
End Function
'Get phone address
Shared Function GetAddress(ByRef Address As String) As String
Dim tmpChar As Char() = Address.ToCharArray
Dim i As Integer, result As String
For i = 0 To tmpChar.GetUpperBound(0) Step 2
result += Swap(tmpChar(i) + tmpChar(i + 1))
Next
If InStr(result, "F") Then result = Mid(result, 1, result.Length - 1)
Return result
End Function
Shared Function GetSMSType(ByVal PDUCode As String) As SMS.SMSType
'Get first october
Dim FirstOctet As Byte
Dim L As Integer = SMS.GetByte(PDUCode)
SMS.GetByte(PDUCode)
SMS.GetString(PDUCode, (L - 1) * 2)
FirstOctet = SMS.GetByte(PDUCode)
'[Chinese]取得特征码
'[Chinese]取得基本码 最后两个bit + 是否有header作为标记
'Get base code. Use last 2 bit and whether there's a header as remark
Dim t1 As Integer = FirstOctet And 3 '00000011
Dim t2 As Integer = FirstOctet And 64 '01000000
'[Chinese]特别处理
If t1 = 3 And t2 = 64 Then Return SMS.SMSType.EMS_SUBMIT
Return t1 + t2
End Function
'Deoce a unicode string
Shared Function DecodeUnicode(ByVal strUnicode As String) As String
Dim Code As String
Dim i, j As Integer
Dim c() As String 'temp
ReDim c(strUnicode.Length / 4) '2 Byte a Unicode char
For j = 0 To strUnicode.Length \ 4 - 1
Dim d() As Char = strUnicode.ToCharArray(j * 4, 4)
c(j) = "&H" & CType(d, String)
c(j) = ChrW(Val(c(j)))
Code += c(j)
Next
Return Code
End Function
'Deocde 7Bit to english
Shared Function Deocde7Bit(ByVal str7BitCode As String) As String
Dim i, j As Integer
Dim Result As String
Dim tmpChar As Char() = str7BitCode.ToCharArray
Dim Dec, m, CharAscii, Reminder, t As Integer
Do Until j > tmpChar.GetUpperBound(0)
i = i Mod 7
Dec = Val("&H" & tmpChar(j) & tmpChar(j + 1))
CharAscii = (Dec And (2 ^ (7 - i) - 1)) * 2 ^ i + Reminder
Reminder = Dec \ 2 ^ (7 - i)
Result += Chr(CharAscii)
If i = 6 Then
Result += Chr(Reminder)
Reminder = 0
End If
i += 1
j += 2
Loop
Return Result
End Function
End Class
Public Class SMS_RECEIVED
Inherits SMS
Public SrcAddressLength As Byte
Public SrcAddressType As Byte
Public SrcAddressValue As String
Public TP_SCTS As Date
Sub New(ByVal PDUCode As String)
Type = SMS.SMSType.SMS_RECEIVED
GetOrignalData(PDUCode)
End Sub
Public Overrides Sub GetOrignalData(ByVal PDUCode As String)
SCAddressLength = GetByte(PDUCode)
SCAddressType = GetByte(PDUCode)
SCAddressValue = GetAddress((GetString(PDUCode, (SCAddressLength - 1) * 2)))
FirstOctet = GetByte(PDUCode)
SrcAddressLength = GetByte(PDUCode)
SrcAddressType = GetByte(PDUCode)
SrcAddressLength += SrcAddressLength Mod 2
SrcAddressValue = GetAddress((GetString(PDUCode, SrcAddressLength)))
TP_PID = GetByte(PDUCode)
TP_DCS = GetByte(PDUCode)
TP_SCTS = GetDate(GetString(PDUCode, 14))
TP_UDL = GetByte(PDUCode)
TP_UD = GetString(PDUCode, TP_UDL * 2)
End Sub
End Class
Public Class SMS_SUBMIT
Inherits SMS
Public TP_MR As Byte
Public DesAddressLength As Byte
Public DesAddressType As Byte
Public DesAddressValue As String
Public TP_VP As Byte
Sub New(ByVal PDUCode As String)
Type = SMS.SMSType.SMS_SUBMIT
GetOrignalData(PDUCode)
End Sub
Public Overrides Sub GetOrignalData(ByVal PDUCode As String)
SCAddressLength = GetByte(PDUCode)
SCAddressType = GetByte(PDUCode)
SCAddressValue = GetAddress((GetString(PDUCode, (SCAddressLength - 1) * 2)))
FirstOctet = GetByte(PDUCode)
TP_MR = GetByte(PDUCode)
DesAddressLength = GetByte(PDUCode)
DesAddressType = GetByte(PDUCode)
DesAddressLength += DesAddressLength Mod 2
DesAddressValue = GetAddress((GetString(PDUCode, DesAddressLength)))
TP_PID = GetByte(PDUCode)
TP_DCS = GetByte(PDUCode)
TP_VP = GetByte(PDUCode)
TP_UDL = GetByte(PDUCode)
TP_UD = GetString(PDUCode, TP_UDL * 2)
End Sub
End Class
Public Class EMS_RECEIVED
Inherits SMS_RECEIVED
Public Structure InfoElem 'See document "How to create EMS"
Public Identifier As Byte
Public Length As Byte
Public Data As String
End Structure
Public TP_UDHL As Byte
Public IE() As InfoElem
Sub New(ByVal PDUCode As String)
MyBase.New(PDUCode)
End Sub
Public Overrides Sub GetOrignalData(ByVal PDUCode As String)
SCAddressLength = GetByte(PDUCode)
SCAddressType = GetByte(PDUCode)
SCAddressValue = GetAddress(GetString(PDUCode, (SCAddressLength - 1) * 2))
FirstOctet = GetByte(PDUCode)
SrcAddressLength = GetByte(PDUCode)
SrcAddressType = GetByte(PDUCode)
SrcAddressLength += SrcAddressLength Mod 2
SrcAddressValue = GetAddress((GetString(PDUCode, SrcAddressLength)))
TP_PID = GetByte(PDUCode)
TP_DCS = GetByte(PDUCode)
TP_SCTS = GetDate(GetString(PDUCode, 14))
TP_UDL = GetByte(PDUCode)
TP_UDHL = GetByte(PDUCode)
IE = GetIE(GetString(PDUCode, TP_UDHL * 2))
TP_UD = GetString(PDUCode, TP_UDL)
End Sub
'Get Informat Elements
Shared Function GetIE(ByVal IECode As String) As InfoElem()
Dim tmp As String = IECode, t As Integer = 0
Dim result() As InfoElem
Do Until IECode = ""
ReDim Preserve result(t)
With result(t)
.Identifier = GetByte(IECode)
.Length = GetByte(IECode)
.Data = GetString(IECode, .Length * 2)
End With
t += 1
Loop
Return result
End Function
End Class
Public Class EMS_SUBMIT
Inherits SMS_SUBMIT
Sub New(ByVal PDUCode As String)
MyBase.New(PDUCode)
Type = SMS.SMSType.EMS_SUBMIT
End Sub
Public TP_UDHL As Byte
Public IE() As EMS_RECEIVED.InfoElem
Public Overrides Sub GetOrignalData(ByVal PDUCode As String)
SCAddressLength = GetByte(PDUCode)
SCAddressType = GetByte(PDUCode)
SCAddressValue = GetAddress(GetString(PDUCode, (SCAddressLength - 1) * 2))
FirstOctet = GetByte(PDUCode)
TP_MR = GetByte(PDUCode)
DesAddressLength = GetByte(PDUCode)
DesAddressType = GetByte(PDUCode)
DesAddressLength += DesAddressLength Mod 2
DesAddressValue = GetAddress(GetString(PDUCode, DesAddressLength))
TP_PID = GetByte(PDUCode)
TP_DCS = GetByte(PDUCode)
TP_VP = GetByte(PDUCode)
TP_UDL = GetByte(PDUCode)
TP_UDHL = GetByte(PDUCode)
IE = EMS_RECEIVED.GetIE(GetString(PDUCode, TP_UDHL * 2))
TP_UD = GetString(PDUCode, TP_UDL * 2)
End Sub
End Class
Public Class SMS_STATUS_REPORT
Inherits SMS_RECEIVED
Public TP_MR As Byte
Public TP_DP As Date
Public Status As Byte
Sub New(ByVal PDUCode As String)
MyBase.New(PDUCode)
Type = SMS.SMSType.SMS_STATUS_REPORT
End Sub
Public Overrides Sub GetOrignalData(ByVal PDUCode As String)
SCAddressLength = GetByte(PDUCode)
SCAddressType = GetByte(PDUCode)
SCAddressValue = GetAddress(GetString(PDUCode, (SCAddressLength - 1) * 2))
FirstOctet = GetByte(PDUCode)
TP_MR = GetByte(PDUCode)
SrcAddressLength = GetByte(PDUCode)
SrcAddressType = GetByte(PDUCode)
SrcAddressLength += SrcAddressLength Mod 2
SrcAddressValue = GetAddress(GetString(PDUCode, SrcAddressLength))
TP_SCTS = GetDate(GetString(PDUCode, 14))
TP_DP = GetDate(GetString(PDUCode, 14))
Status = GetByte(PDUCode)
'Status report do not have content so I set it a zero length string
TP_UD = ""
End Sub
End Class