Imports TComm.Sock.Client Imports TComSettings.Sock 'Imports CommunicationSettings.SWSockets Imports CR.Bytes Imports TComm.Sock Imports CommunicationSettings.SWSockets Public Interface IOpenCloseSend Property Message As String Property SMSNumber As String End Interface Public Class SMSClient Inherits TComm.Sock.Client.SimpleAsyncClient Private _ph As CodeEx.STypes.TDWrapper ' CR.PropertyHelper(Of SMSLData) Private _phreply As CodeEx.STypes.TDWrapper ' New CR.PropertyHelper(Of SMSReplyData) Private _LastmdataHolder As New LastSMSLdataHolder Private _portandspanattemptcount As Integer Private _smsreceiveHandler As ISMSHandler Private _isAttemptingPortCheck As Boolean = False Private _isOpenandCloseSend As IOpenCloseSend Sub New(settings As TComSettings.Sock.ISMSSetting, parent As ISMSHandler) MyBase.New() Init(settings, Nothing) _smsreceiveHandler = parent _ph = CodeEx.STypes.Discover.GetWrapper(Of SMSLData) _phreply = CodeEx.STypes.Discover.GetWrapper(Of SMSReplyData) ' TComSettings.Sock.ISMSSettings End Sub Public Property SMSSettings As TComSettings.Sock.ISMSSetting Set(value As TComSettings.Sock.ISMSSetting) _settings = value End Set Get Return _settings End Get End Property 'Protected Overrides Sub o(sb As SocBuff, ReceivDataLen As Integer) 'End Sub 'Public Function OpenandCloseSend(ios As IOpenCloseSend) ' _isOpenandCloseSend = ios ' Dim ret As Boolean ' ret = Me.Connectandstart ' Return ret 'End Function 'Protected Overrides ReadOnly Property ReadOnconnect As Boolean ' Get ' Return False ' End Get 'End Property Private Function SendandWaitAt(ba As ByteAppender, ac As AsyncCallback) As Boolean Dim si As New SendInfo(ba, ac) si.ReplyRequired = True 'Me.Send(si) Me.Send(ba, True, ac) Return True End Function Private Function SendMyData(ba As ByteAppender, breplyrequired As Boolean) As Boolean Dim si As New SendInfo(ba) si.ReplyRequired = True 'Me.Send(si) Me.Send(ba) Return True End Function Private Function ReceiveAt(sbrec As SendInfo, ac As AsyncCallback) As Boolean Dim si As New SendInfo(sbrec, Settings.ReceiveBuffLen, ac) si.ReplyRequired = True 'Me.AwaitReply(si) Me.TryReceive(ac) Return True End Function Public Overrides Function Connect() As Boolean If MyBase.Connect Then Try Threading.Thread.Sleep(200) Dim settings As TComSettings.Sock.ISMSSetting = Me._settings Dim BB As New CR.Bytes.ByteAppender("Action: login" & vbCrLf) BB.Append("Username: " & settings.UserID & vbCrLf) LogInDebug("sending " & BB.GetCPlusPlusString) BB.Append("Secret: " & settings.Password & vbCrLf) BB.Append(vbCrLf) LogInDebug("sending " & "Secret: ******\r\n\r\n") 'Return SendandWaitAt(BB, New AsyncCallback(AddressOf LoginReply)) Send(BB, True, New AsyncCallback(AddressOf LoginReply)) Catch ex As Exception LogException("OnOpen", ex) Return False End Try End If End Function Private Shared Function SplitByLineFeed(str As String) As List(Of String) Dim lst As New List(Of String) Dim sarr As String() = str.Split(vbLf) For Each strf As String In sarr strf = strf.Replace(vbCr, "") If strf.Length > 0 Then lst.Add(strf) End If Next Return lst End Function Public Sub SendPortrequest() _isAttemptingPortCheck = True Dim settings As TComSettings.Sock.ISMSSetting = Me._settings Dim BB As New CR.Bytes.ByteAppender("Action: smscommand" & vbCrLf) BB.Append("command: gsm show span " & CStr(settings.SMSPortNo)) BB.Append(vbCrLf & vbCrLf) _settings.ReceiveBuffLen = 3000 _portandspanattemptcount = 0 LogInDebug("sent " & BB.GetCPlusPlusString) SendMyData(BB, False) _settings.ReceiveBuffLen = 2000 ' Client->Server 'command: “Action: smscommand\r\ncommand: gsm show $port+1\r\n\r\n” '$port: the port you want to check End Sub Public Sub AwaitPortresult(ByVal ar As IAsyncResult) Dim sb As BaseInfoSoc = ReadResult(ar) If sb Is Nothing Then LogAlways("LoginReply sb was nothing ") Return End If If sb.ByteCount = 0 Then LogAlways("LoginReply zerodata received ") End If Dim lst As List(Of ByteAppender) = sb.ba.SplitByLineFeed() Dim bfinished As Boolean Dim bisok As Boolean For Each ba As ByteAppender In lst If ba.GetString.Contains("Power on") Then If ba.GetString.Contains("Provisioned") Then If ba.GetString.Contains("Active") Then bisok = True Exit For End If End If End If Next If lst.Count > 0 Then If lst(lst.Count - 1).GetString.Contains("--END COMMAND--") Then bfinished = True End If End If If bfinished Then If Not bisok Then LogAlways("problem with reply " & sb.ba.GetString) End If GotoNewSMSAwait(sb) Else If _portandspanattemptcount < 5 Then _portandspanattemptcount += 1 sb = New SendInfo(sb, Settings.ReceiveBuffLen, AddressOf AwaitPortresult) AwaitReply(sb) Else GotoNewSMSAwait(sb) End If End If End Sub Private Sub GotoNewSMSAwait(sb As BaseInfoSoc) Dim settings As TComSettings.Sock.ISMSSetting = Me._settings Dim sbnew As New SendInfo(sb, settings.ReceiveBuffLen, New AsyncCallback(AddressOf AwaitSMS)) 'sbnew.ClientSoc = sb.ClientSoc LogAlways("Await SMS") AwaitReply(sbnew) ' ReceiveAt(sbnew, New AsyncCallback(AddressOf AwaitSMS)) End Sub Protected Sub LoginReply(ByVal ar As IAsyncResult) Try 'Dim sb As BaseInfoSoc = ReadResult(ar) Dim ba As ByteAppender = EndReceive(ar) If ba IsNot Nothing Then LogAlways("LoginReply sb was nothing ") Return End If Dim bcomplete As Boolean Dim str As String = ba.GetString If str.EndsWith(vbCrLf & vbCrLf) Then Dim lst As List(Of String) = SplitByLineFeed(str) For Each strf As String In lst If strf.Contains("Authentication accepted") Then bcomplete = True End If Next End If If Not bcomplete Then 'ReceiveAt(sb, New AsyncCallback(AddressOf LoginReply)) TryReceive(New AsyncCallback(AddressOf LoginReply), ba) Return End If 'Action: smscommand\r\ncommand: gsm show spans\r\n\r\n Dim BB As New CR.Bytes.ByteAppender("Action: smscommand" & vbCrLf) 'MyBase.Senddata(bb,False ) BB.Append("command: gsm show spans" & vbCrLf & vbCrLf) _settings.ReceiveBuffLen = 3000 _portandspanattemptcount = 0 LogInDebug("sent " & BB.GetCPlusPlusString) 'SendandWaitAt(BB, New AsyncCallback(AddressOf AwaitspansResult)) Send(BB, True, New AsyncCallback(AddressOf AwaitspansResult)) _settings.ReceiveBuffLen = 2000 Catch ex As Exception LogException("LoginRely", ex) End Try End Sub Protected Sub AwaitspansResult(ByVal ar As IAsyncResult) Try 'Dim sb As BaseInfoSoc = ReadResult(ar) Dim ba As ByteAppender = EndReceive(ar) If ar Is Nothing Then LogAlways("AwaitspansResult sb was nothing ") Return End If If ba IsNot Nothing Then Dim settings As TComSettings.Sock.ISMSSetting = Me._settings Dim bfinished As Boolean Dim lst As New List(Of String) Dim str As String = ba.GetString If str.EndsWith(vbCrLf & vbCrLf) Then bfinished = True lst = SplitByLineFeed(str) ', vbCrLf, foundcount) Dim teststring As String = "GSM span " & settings.SMSPortNo & ": Power on, Provisioned, Up, Active" For i = 0 To lst.Count - 1 If lst(i).Contains(teststring) Then If lst(lst.Count - 1).Contains("--END COMMAND--") Then LogAlways("Port " & settings.SMSPortNo & " OK ") End If End If Next End If If bfinished Then If _isOpenandCloseSend Is Nothing Then 'Dim sbnew As New SendInfo(ba, settings.ReceiveBuffLen, New AsyncCallback(AddressOf AwaitSMS)) Dim sbnew As New Send(ba, settings.ReceiveBuffLen, New AsyncCallback(AddressOf AwaitSMS)) ' sbnew.ClientSoc = sb.ClientSoc LogAlways("Await SMS") AwaitReply(sbnew) ' ReceiveAt(sbnew, New AsyncCallback(AddressOf AwaitSMS)) Else Me.SendMessage(_isOpenandCloseSend.SMSNumber, New ByteAppender(_isOpenandCloseSend.Message)) _isOpenandCloseSend = Nothing Me.CloseandStop() End If Else If _portandspanattemptcount < 5 Then _portandspanattemptcount += 1 ReceiveAt(sb, New AsyncCallback(AddressOf AwaitspansResult)) End If End If Else LogAlways("AwaitspansResult no data") End If Catch ex As Exception LogException("AwaitspansResult", ex) End Try End Sub Private _lastPk As Integer = -1 Private Function RunCompletedSMS(SMSLData As SMSLData) As Boolean 'Dim prefix As String = _parent._Siteinfo.AuthorityPrefix 'Dim smtemp As SMSDataTemp = SMSLData.GetNewSMSDataTemp(Me) 'If smtemp Is Nothing Then ' Return False 'End If 'Dim authonumber As String 'smtemp.AuthorisationNo = prefix 'smtemp.Status = RMApp.ClientStatus.UnConfirmed 'If _parent._Siteinfo.RequireConfimation Then ' smtemp.SMSData_ID = 0 'Else ' smtemp.SMSData_ID = -1 'End If 'DAL.Serv.SMSDataTempSv.Inst.SaveObject(smtemp) 'A trigger will automatically append the primary key to the AuthorityNo 'smtemp.AuthorisationNo = prefix & smtemp.PrimaryKey 'we still need to do it in code unless we get the database object by query 'If Not _parent._Siteinfo.RequireConfimation Then ' Dim smdat As SMSData = SMSLData.GetNewSMSData(Me) ' smdat.AuthorisationNo = smtemp.AuthorisationNo ' DAL.Serv.SMSDataSv.Inst.SaveObject(smdat) ' smtemp.SMSData_ID = smdat.PrimaryKey ' If smtemp.PrimaryKey <> 0 Then ' DAL.Serv.SMSDataTempSv.Inst.SaveObjectOneProperty(smtemp, SMSDataTemp.Prop.SMSData_ID) ' Else ' LogAlways("sdtemp primary key not updated on save") ' End If 'End If 'Dim str As String = SMSLData.GetReadablecontent 'If str <> "" Then ' Dim ba As ByteAppender = _parent.getReplyString(str, smtemp.AuthorisationNo) ' LogInDebug("sending " & ba.GetCPlusPlusString) ' SendMessage(SMSLData.Sender, ba) ' Return True 'End If 'Return False End Function Private Sub AwaitSMS(ByVal ar As IAsyncResult) Dim sbrec As BaseInfoSoc = ar If _isAttemptingPortCheck Then _isAttemptingPortCheck = False AwaitPortresult(ar) Return End If Try 'sb = GetReadResult(ar) If sbrec Is Nothing Then LogAlways("AwaitSMS sb was nothing ") Return End If If sbrec.ByteCount > 0 Then Dim msgsent As Boolean Dim bb As ByteAppender = sbrec.ba ' Dim buff As Byte() = bb.GetLastBuff(19) If bb.Endswith("--END SMS EVENT--" & vbCrLf & vbCrLf) Then Dim smsd As New SMSLData(bb, _ph) LogInDebug("received " & smsd.ToString) smsd = _LastmdataHolder.UpdatelastSend(smsd) If smsd.IsComplete Then If _smsreceiveHandler IsNot Nothing Then Dim ba As ByteAppender = _smsreceiveHandler.RunCompletedSMS(smsd) If ba IsNot Nothing Then msgsent = SendMessage(smsd.Sender, ba) End If End If End If Dim si = New SendInfo(sbrec, bb, New AsyncCallback(AddressOf LoginReply)) ' _settings.ReceiveBuffLen) Me.Send(si) 'si.asc = New AsyncCallback(AddressOf LoginReply) ' Dim si As New SendInfo(BB, New AsyncCallback(AddressOf LoginReply)) If msgsent Then LogInDebug("SMSReply") ReceiveAt(sbrec, New AsyncCallback(AddressOf SMSReply)) 'ReceiveAt(sb, New AsyncCallback(AddressOf SMSReply)) Return Else LogInDebug("AwaitSMS") ReceiveAt(sbrec, New AsyncCallback(AddressOf AwaitSMS)) 'si = New SendInfo(sbrec, bb, New AsyncCallback(AddressOf AwaitSMS)) ' _settings.ReceiveBuffLen) 'Me.Send(si) ' ReceiveAt(sb, New AsyncCallback(AddressOf AwaitSMS)) Return End If Else LogInDebug("AwaitSMS again") Dim rbh As New ReplyBuffHolder(sbrec, New AsyncCallback(AddressOf AwaitSMS)) rbh.AddSpaceAfterTotalReceived(sbrec.ba, _settings.ReceiveBuffLen) AwaitReply(rbh) 'sb.BB.Resize(sbl.TotalReceiveen + _settings.ReceiveBuffLen) 'ReceiveAt(sb, New AsyncCallback(AddressOf AwaitSMS)) Return End If Else LogInDebug("Exiting Await SMS receivelen 0") End If Catch ex As Exception LogException("AwaitSMS", ex) If sbrec IsNot Nothing Then LogAlways(sbrec.ba.GetCPlusPlusString) End If ' sb = New SendInfo(sb, _settings.ReceiveBuffLen) ReceiveAt(sbrec, New AsyncCallback(AddressOf SMSReply)) End Try ' “ID” the unique identifier of these SMS; '“GsmPort”: the port that received the SMS; '“Sender”: the Number that sent the SMS; '“Recvtime”: received time; '“Index”: sequence Number of the SMS piece '“Total”: how many pieces of SMS Is sent as a whole '“Smsc”: SMS center number 'Content: SMS content '--END SMS EVENT— ' Event: ReceivedSMS 'Privilege: all,smscommand 'ID: E9510086 'GsmPort: 5 'Sender: 10086 'Recvtime: 2013-11-13 14:59:13 'Index: 2 'Total: 2 'Smsc: +8613800591551 'Content: %EF%BB%BF%E8%BF%87%E7%9F%AD%E4%BF%A1%E3%80%81%E8%AF%AD%E9%9F%B3%E3%80%81%E7%BD%91%E7%AB%99%E8%87%AA%E5%8A%A9%E4%BA%A4%E8%B4%B9%EF%BC%8C%E6%9B%B4%E5%8F%AF%E4%BA%AB%E5%8F%979.8%E6%8A%98%E4%BC%98%E6%83%A0%EF%BC%8C%E8%AF%A6%E6%83%85%E7%99%BB%E9%99%86www.10086.cn%E6%9F%A5%E8%AF%A2%E3%80%82%E4%B8%AD%E5%9B%BD%E7%A7%BB%E5%8A%A8 End Sub Private Sub SMSReply(ByVal ar As IAsyncResult) Try Dim sbrec As BaseInfoSoc = ReadResult(ar) If sbrec Is Nothing Then LogAlways("SMSReply sb was nothing ") Return End If If sbrec.ByteCount > 0 Then Dim bb As ByteAppender = sbrec.ba If bb.Endswith("--END SMS EVENT--" & vbCrLf & vbCrLf) Then Dim smsr As New SMSReplyData(bb, _phreply) If smsr.Status <> "1" Then LogAlways("SMS failed id " & smsr.ID & " status " & smsr.Status) End If ' sb = New SendInfo(_settings.ReceiveBuffLen) ''' todo create Aawait sms response then go to await sms LogInDebug("AwaitSMS") ReceiveAt(sbrec, New AsyncCallback(AddressOf AwaitSMS)) Else Dim rb As New ReplyBuffHolder(sbrec, New AsyncCallback(AddressOf SMSReply)) rb.AddSpaceAfterTotalReceived(sbrec.ba, _settings.ReceiveBuffLen) 'sb.Ba.Resize(sb.TotalReceivelen + _settings.ReceiveBuffLen) ReceiveAt(sbrec, New AsyncCallback(AddressOf SMSReply)) Return End If End If Catch ex As Exception LogException("SMSReply", ex) End Try End Sub 'Protected Overrides ReadOnly Property AlwayTryRead As Boolean ' Get ' Return False ' End Get 'End Property 'Protected Overrides Function GetReadResult(ar As IAsyncResult) As BaseInfoSoc ' Dim sb As BaseInfoSoc = ar.AsyncState ' If sb IsNot Nothing Then ' Try ' If Not isConnected Then ' LogAlways("Not connected GetReadResult") ' sb.ShouldReconnect = True ' sb.ReceiveLen = -1 ' Return sb ' End If ' sb.ReceiveLen = sb.ClientSoc.EndReceive(ar) ' If sb.ReceiveLen > 0 Then ' _lastActionOnPort = Now ' ' sb.ClearExcesssBytes(sb.ReceiveLen) ' If _settings.AlwaysLogRead Then ' LogAlways("received on " & sb.ClientSoc.RemoteEndPoint.ToString & " " & sb.BB.GetCPlusPlusStringAt(sb.PreviousRecvlen, sb.ReceiveLen)) ' End If ' Else ' SetStatusLogReset(sb, NmCommunication.StatusMessage.NoDataReceived) ' End If ' Catch ex As Exception ' sb.ShouldReconnect = True ' SetStatusLogReset(sb, NmCommunication.StatusMessage.Exception_Received, ex, "") ' sb.ReceiveLen = -1 ' Finally ' End Try ' End If ' Return sb 'End Function Private Function SendData(bb As ByteAppender, replyrequired As Boolean) Dim si As New SendInfo(bb) si.ReplyRequired = replyrequired Me.Send(si) Return True End Function Public Function SendMessage(smsNumber As String, basend As ByteAppender) As Boolean Dim ret As Boolean Try ' Dim BB As New CR.Bytes.ByteAppender("Action: smscommand" & vbCrLf) 'BB.Append("command: gsm show " & CStr(settings.SMSPortNo)) 'BB.Append(vbCrLf & vbCrLf) Dim settings As TComSettings.Sock.ISMSSetting = Me._settings If isConnected Then Dim bb As New ByteAppender("Action: smscommand" & vbCrLf) bb.Append("command: gsm send sms ") bb.Append(settings.SMSPortNo & " " & smsNumber & " " & Chr(34) & basend.GetUrlEncoded & Chr(34) & " " & settings.CurrentSendingID & vbCrLf) bb.Append(vbCrLf) ret = Me.SendData(bb, False) settings.CurrentSendingID += 1 settings.SaveSendingId() ' DAL.Serv.NeogateSettingSv.Inst.SaveObjectOneProperty(settings, "CurrentSendingID") Else LogAlways(settings.Name & " trying to send when not connected") End If Catch ex As Exception LogException("SendMessage", ex) End Try Return ret End Function Protected Overrides Sub ReconnectOrHeartBeatAfterRegularWait() If Not _ExternalDisconnect Then SendPortrequest() End If End Sub 'Protected Overrides Sub ReconnectTread() ' While Not _disconnect ' If _isReconnecting Then ' If Not Waitthirtysecs() Then ' Exit While ' Else ' Reconnect() ' End If ' Else ' For i = 0 To ClientSettings.RegularConnectSeconds / 30 ' If Not Waitthirtysecs() Then ' Exit While ' End If ' If _isReconnecting Then ' Exit For ' Else ' If DateAdd(DateInterval.Second, ClientSettings.RegularConnectSeconds, _lastActionOnPort) < Now Then ' If isConnected Then ' If Not _disconnect Then ' SendPortrequest() '' instead of reconnecting try just sending port request as heartbeat ' Else ' Exit While ' End If ' Else ' Reconnect() ' End If ' End If ' End If ' Next ' End If ' End While ' LogInDebug(Me.ClientSettings.ConnectionName & " Exiting reconnection Thread") ' _reglarReconnectRunning = False 'End Sub Public Overrides Function onReadOK(rinfio As BaseInfoSoc) As SendInfo Return MyBase.onReadOK(rinfio) End Function Protected Overrides Sub OnConnectOK() MyBase.OnConnectOK() Try Threading.Thread.Sleep(200) Dim settings As TComSettings.Sock.ISMSSetting = Me._settings Dim BB As New CR.Bytes.ByteAppender("Action: login" & vbCrLf) BB.Append("Username: " & settings.UserID & vbCrLf) LogInDebug("sending " & BB.GetCPlusPlusString) BB.Append("Secret: " & settings.Password & vbCrLf) BB.Append(vbCrLf) LogInDebug("sending " & "Secret: ******\r\n\r\n") Dim si As New SendInfo(BB, New AsyncCallback(AddressOf LoginReply)) MyBase.Send(si) Return ' Return MyBase.SendandWaitAt(BB, New AsyncCallback(AddressOf LoginReply)) Catch ex As Exception LogException("OnOpen", ex) Return End Try End Sub 'Protected Overrides Sub ReconnectTread() ' While Not _disconnect ' If _isReconnecting Then ' If Not Waitthirtysecs() Then ' Exit While ' Else ' Connect() ' End If ' Else ' For i = 0 To ClientSettings.RegularConnectSeconds / 30 ' If Not Waitthirtysecs() Then ' Exit While ' End If ' If _isReconnecting Then ' Exit For ' Else ' If DateAdd(DateInterval.Second, ClientSettings.RegularConnectSeconds, _lastActionOnPort) < Now Then ' If isConnected Then ' If Not _disconnect Then ' TryReconnect() ' Else ' Exit While ' End If ' Else ' Connect() ' End If ' End If ' End If ' Next ' End If ' End While ' LogInDebug(Me.ClientSettings.ConnectionName & " Exiting reconnection Thread") ' _reglarReconnectRunning = False 'End Sub End Class