13.8.09

dotNet send and receive SMS via PC Connectivity API

ค้างไว้เมื่อตอนก่อนหน้านี้ ครั้งนี้จะมาเขียนรับ/ส่ง sms โดยใช้ Nokia PC Connectivity API โค้ดนี้ไม่ได้เขียนเองทั้งหมดบางส่วนหยิบมาจาก forumn ของ nokia แต่ผมนำมาเขียนส่วนของการรับ sms เพิ่มเข้าไป

โค้ดบางส่วน

Imports System.Runtime.InteropServices

Public Class SMS

Public Shared Sub ReadSMS(ByVal strSerialNumber As String)
Dim intSMSHandle As Integer = 0
Dim intOperationHandle As Integer = 0
Dim intStatusCode As Integer = CAAPI_Initialize(30, 0)

intSMSHandle = OpenSMSConnection(strSerialNumber)

Dim folderInfo As CA_FOLDER_INFO
folderInfo = New CA_FOLDER_INFO
folderInfo.iSize = Marshal.SizeOf(folderInfo)
folderInfo.iFolderId = CA_MESSAGE_FOLDER_INBOX
Dim bufFolderInfo As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_FOLDER_INFO)))
Marshal.StructureToPtr(folderInfo, bufFolderInfo, True)
intStatusCode = CAGetFolderInfo(intSMSHandle, bufFolderInfo)

intStatusCode = CABeginOperation(intSMSHandle, 0, intOperationHandle)
If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CABeginOperation-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If

Dim caIDList As CA_ID_LIST
caIDList.iSize = Marshal.SizeOf(caIDList)
Dim bufList As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(caIDList))
Marshal.StructureToPtr(caIDList, bufList, True)
intStatusCode = CAGetIDList(intSMSHandle, folderInfo.iFolderId, 0, bufList)
caIDList = Marshal.PtrToStructure(bufList, GetType(CA_ID_LIST))

Dim i As Integer = 0
For i = 1 To caIDList.iUIDCount
Dim itemId As CA_ITEM_ID
itemId.iSize = Marshal.SizeOf(itemId)
itemId.iFolderId = CA_MESSAGE_STATUS_READ
itemId.iStatus = 0
itemId.iTemporaryID = i
itemId.iUidLen = 0
itemId.pbUid = IntPtr.Zero
Dim bufItemId As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ITEM_ID)))
Marshal.StructureToPtr(itemId, bufItemId, True)

Dim dataSMS As CA_DATA_MSG
dataSMS.iSize = Marshal.SizeOf(dataSMS)
dataSMS.bAddressCount = 0
dataSMS.iDataLength = 0
dataSMS.iInfoField = 0
dataSMS.pAddress = IntPtr.Zero
dataSMS.pbData = IntPtr.Zero
Dim bufDataSMS As IntPtr = Marshal.AllocHGlobal(dataSMS.iSize)
Marshal.StructureToPtr(dataSMS, bufDataSMS, True)

intStatusCode = CAReadItem(intOperationHandle, bufItemId, CA_OPTION_USE_CACHE, CA_DATA_FORMAT_STRUCT, bufDataSMS)
If intStatusCode = CONA_OK Then
dataSMS = Marshal.PtrToStructure(bufDataSMS, GetType(CA_DATA_MSG))
Dim message As String = Marshal.PtrToStringUni(dataSMS.pbData, dataSMS.iDataLength / 2)
' something ...
Else
Throw New Exception("Error in CAReadItem-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
Next

intStatusCode = CAEndOperation(intOperationHandle)
If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CAEndOperation-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
CloseSMSConnection(intSMSHandle)

End Sub

Public Shared Sub SendSMS(ByVal strSerialNumber As String, ByVal strPhoneNo As String, _
ByVal strMessage As String, ByVal boolDontDelete As Boolean)

Dim intSMSHandle As Integer = 0

Dim intStatusCode As Integer = CAAPI_Initialize(30, 0)

Try
intSMSHandle = OpenSMSConnection(strSerialNumber)

Try
Dim folderInfo As CA_FOLDER_INFO
folderInfo = New CA_FOLDER_INFO
folderInfo.iSize = Marshal.SizeOf(folderInfo)
Dim bufItem As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_FOLDER_INFO)))
Marshal.StructureToPtr(folderInfo, bufItem, True)
intStatusCode = CAGetFolderInfo(intSMSHandle, bufItem)

Dim intOperationHandle As Integer = 0
intStatusCode = CABeginOperation(intSMSHandle, 0, intOperationHandle)
If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CABeginOperation-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If

Dim itemUid As CA_ITEM_ID
itemUid.iSize = Marshal.SizeOf(itemUid)
itemUid.iFolderId = CA_MESSAGE_STATUS_SENT
itemUid.iStatus = 0
itemUid.iTemporaryID = 0
itemUid.iUidLen = 0
itemUid.pbUid = IntPtr.Zero
Dim buf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ITEM_ID)))
Marshal.StructureToPtr(itemUid, buf, True)

Dim objSMSMessage As CA_DATA_MSG
objSMSMessage.iSize = Marshal.SizeOf(objSMSMessage)
CA_SET_DATA_FORMAT(objSMSMessage.iInfoField, CA_DATA_FORMAT_UNICODE)
CA_SET_DATA_CODING(objSMSMessage.iInfoField, CA_DATA_CODING_UNICODE)
CA_SET_MESSAGE_STATUS(objSMSMessage.iInfoField, CA_MESSAGE_STATUS_DRAFT)
CA_SET_MESSAGE_TYPE(objSMSMessage.iInfoField, CA_SMS_SUBMIT)

objSMSMessage.bAddressCount = 1
objSMSMessage.pAddress = CreateSMSPhoneNoReference(strPhoneNo)

objSMSMessage.iDataLength = strMessage.Length * 2
objSMSMessage.pbData = Marshal.StringToCoTaskMemUni(strMessage)

CreateTimestamp(objSMSMessage.messageDate)

Dim buf2 As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_DATA_MSG)))
Marshal.StructureToPtr(objSMSMessage, buf2, True)

intStatusCode = CAWriteItem(intOperationHandle, buf, 0, CA_DATA_FORMAT_STRUCT, buf2)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CAWriteItem-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If

Marshal.FreeHGlobal(buf2)
Marshal.FreeHGlobal(buf)
Marshal.FreeCoTaskMem(objSMSMessage.pbData)
Marshal.FreeCoTaskMem(objSMSMessage.pAddress)

Dim lstIDs As CA_ID_LIST
lstIDs.iSize = Marshal.SizeOf(GetType(CA_ID_LIST))
Dim lstbuf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(CA_ID_LIST)))
Marshal.StructureToPtr(lstIDs, lstbuf, True)

intStatusCode = CACommitOperations(intOperationHandle, lstbuf)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CACommitOperations-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If

If Not boolDontDelete Then
' Picking the first (and only) message from list and deleting it
lstIDs = Marshal.PtrToStructure(lstbuf, GetType(CA_ID_LIST))
Dim objViestiUID As CA_ITEM_ID = GetUidFromBuffer(0, lstIDs.pUIDs)

DeleteMessage(intOperationHandle, objViestiUID)

intStatusCode = CACommitOperations(intOperationHandle, IntPtr.Zero)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CACommitOperations-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
End If

intStatusCode = CAEndOperation(intOperationHandle)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CAEndOperation-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
Catch ex As Exception
Throw ex
Finally
CloseSMSConnection(intSMSHandle)
End Try
Catch ex As Exception
Throw ex
Finally
CAAPI_Terminate(0)
End Try
End Sub

Private Shared Sub DeleteMessage(ByVal intOperationHandle As Integer, ByVal objItem As CA_ITEM_ID)
Dim bufViesti As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(objItem))
Marshal.StructureToPtr(objItem, bufViesti, True)
Dim intStatusCode As Integer = CADeleteItem(intOperationHandle, bufViesti, 0)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in CADeleteItem-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
End Sub

Private Shared Function GetUidFromBuffer(ByVal iIndex As Integer, ByVal pUIds As IntPtr) As CA_ITEM_ID
' Calculate beginning of item 'iIndex'
Dim iPtr As Int64 = pUIds.ToInt64 + (iIndex * Marshal.SizeOf(GetType(CA_ITEM_ID)))
' Convert integer to pointer
Dim ptr As IntPtr = IntPtr.op_Explicit(iPtr)
' Copy data from buffer
GetUidFromBuffer = Marshal.PtrToStructure(ptr, GetType(CA_ITEM_ID))
End Function

Private Shared Function OpenSMSConnection(ByVal strSerialNumber As String) As Integer
Dim pstrSerialNumber As IntPtr = Marshal.StringToCoTaskMemUni(strSerialNumber)
Dim iMedia As Integer = API_MEDIA_ALL
Dim iTarget As Integer = CA_TARGET_SMS_MESSAGES
Dim intSMSHandle As Integer = 0
Dim intStatusCode As Integer = DAOpenCA(pstrSerialNumber, iMedia, iTarget, intSMSHandle)

If intStatusCode <> CONA_OK Then
Throw New Exception("Error in DAOpenCA-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If

Marshal.FreeCoTaskMem(pstrSerialNumber)

Return intSMSHandle
End Function

Private Shared Sub CloseSMSConnection(ByVal intSMSHandle As Integer)
' Close PIM connection
Dim intStatusCode As Integer = DACloseCA(intSMSHandle)
If intStatusCode <> CONA_OK Then
Throw New Exception("Error in DACloseCA-function: " & CONAError2String(intStatusCode) & " (" & intStatusCode.ToString & ")")
End If
End Sub

Private Shared Function CreateSMSPhoneNoReference(ByVal strNumber As String) As IntPtr
Dim dataAddress As CA_DATA_ADDRESS
dataAddress = New CA_DATA_ADDRESS
dataAddress.iSize = Marshal.SizeOf(dataAddress)
dataAddress.iAddressInfo = CA_MSG_ADDRESS_TYPE_NUMBER
dataAddress.pstrAddress = strNumber
' Allocate memory for buffer
Dim bufDataAddress As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(dataAddress))
Marshal.StructureToPtr(dataAddress, bufDataAddress, True)
Return bufDataAddress
End Function

Private Shared Sub CreateTimestamp(ByRef pimDate As CA_DATA_DATE)
Dim dateCurrent As Date = Date.Now
pimDate.iSize = Marshal.SizeOf(pimDate)
pimDate.wYear = System.Convert.ToUInt16(dateCurrent.Year)
pimDate.bMonth = dateCurrent.Month
pimDate.bDay = dateCurrent.Day
pimDate.bHour = dateCurrent.Hour
pimDate.bMinute = dateCurrent.Minute
pimDate.bSecond = dateCurrent.Second
End Sub
End Class

1 comment:

  1. what is the strSerialNumber in SendSMS(ByVal strSerialNumber As String, ByVal strPhoneNo As String,ByVal strMessage As String, ByVal boolDontDelete As Boolean) function?
    What should be passed in strSearialNumber? what is that number exactly?

    ReplyDelete