
' Interface to an Evolution RCC for image recognition

Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading



Module modRccClient
    Public strRccSendMessage As String = ""
    Public strRccReceiveMessage As String = ""
    Public evntRccDataWaitingToSend As New ManualResetEvent(False)
    Public booRccDataWaitingToSend As Boolean = False
    Public evntRccDataSent As New ManualResetEvent(False)
    Public evntRccDataReceived As New ManualResetEvent(False)
    Public evntRccClientDataPassed As New ManualResetEvent(False)
    Dim intNoResponseCounter As Integer = 0

    Public Function ftnRcc_Communicate(ByVal strCommand As String, ByVal strResponse As String, ByVal intTimeOut As Integer) As String
        ftnRcc_Communicate = ""
        Try
            If boolEnableRcc And classRccClient.Connected And Not boolShutDown Then
                ftnSendCommandRcc(strCommand)
                If (strResponse <> "") Then ftnRcc_Communicate = ftnWaitForExpectedResponseRcc(strResponse, intTimeOut)
                If boolDebugER1IF Then
                    frmDebug.subWriteLogs(ftnElapsedTimeS() & " ftnRcc_Communicate:  sent =      " & strCommand)
                    frmDebug.subWriteLogs(ftnElapsedTimeS() & " ftnRcc_Communicate:  received =  " & ftnRcc_Communicate)
                End If
            End If
        Catch ex As Exception
            frmDebug.subWriteLogs(" EXCEPTION in ftnRcc_Communicate :  " & ex.ToString)
        End Try
    End Function


    Function ftnSendCommandRcc(ByVal strCommand As String) As String
        ftnSendCommandRcc = ""
        Try
            If boolEnableRcc And classRccClient.Connected And Not boolShutDown Then
                evntRccClientDataPassed.Reset()
                strRccSendMessage = strCommand & vbCrLf
                booRccDataWaitingToSend = True
                evntRccDataWaitingToSend.Set()
            End If
        Catch ex As Exception
            frmDebug.subWriteLogs(" EXCEPTION in ftnSendCommandRcc :  " & ex.ToString)
            ftnSendCommandRcc = ""
        End Try
    End Function


    Function ftnWaitForExpectedResponseRcc(ByVal strTextToWaitFor As String, ByVal intTimeOut As Integer) As String
        ftnWaitForExpectedResponseRcc = ""
        Try
            Dim timeOut As DateTime = Now().AddMilliseconds(intTimeOut)
            Do
                ftnWaitForExpectedResponseRcc &= ftnGetTextRcc(150)
            Loop Until ((Now() > timeOut) Or CBool(InStr(ftnWaitForExpectedResponseRcc, strTextToWaitFor)) Or boolStop Or boolShutDown)
        Catch ex As Exception
            frmDebug.subWriteLogs(" EXCEPTION in ftnWaitForExpectedResponseRcc :  " & ex.ToString)
        End Try
    End Function

    Dim boolWaitingForData As Boolean = False
    Public Function ftnGetTextRcc(ByVal intTimeOut As Integer) As String  'must be thread safe
        ftnGetTextRcc = ""
        Try
            If classRccClient.Connected And Not boolShutDown Then
                boolWaitingForData = True
                If (intTimeOut > 0) Then evntRccDataReceived.WaitOne(intTimeOut) ' 
                ftnGetTextRcc = strRccReceiveMessage
                strRccReceiveMessage = ""
                boolWaitingForData = False
                evntRccDataReceived.Reset()
                evntRccClientDataPassed.Set()
            End If
        Catch ex As Exception
            frmDebug.subWriteLogs(" EXCEPTION in ftnGetTextRcc :  " & ex.ToString)
        End Try
    End Function



#Region "RccClient"

    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    '
    '
    '  Example adapted from http://msdn.microsoft.com/en-us/library/bew39x2a(v=VS.100).aspx
    '

    '
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Dim boolErrorDetected As Boolean = False

    Public Class classRccClient
        Public Shared evntConnectDone As New ManualResetEvent(False) ' ManualResetEvent instances signal completion.
        Public Shared Connected As Boolean = False



        Public Sub subMain()
            Try
                While Not boolShutDown
                    classRccClient.Connected = False
                    boolErrorDetected = False
                    intNoResponseCounter = 0
                    Dim RccEndPoint As New IPEndPoint(IPAddress.Parse("127.0.0.1"), 9000) ' Create a TCP/IP socket.
                    Dim RccClientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                    RccClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1500)
                    RccClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1500)
                    RccClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1)
                    RccClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, True)

                    If boolEnableRcc And Not classRccClient.Connected And Not boolErrorDetected And Not boolShutDown Then 'Connect and initialize
                        Thread.Sleep(100)
                        evntConnectDone.Reset()
                        RccClientSocket.BeginConnect(RccEndPoint, New AsyncCallback(AddressOf subConnectCallback), RccClientSocket)
                        evntConnectDone.WaitOne(1500)
                        If classRccClient.Connected And Not boolShutDown Then subReceive(RccClientSocket)
                    End If

                    intNoResponseCounter = 0
                    While classRccClient.Connected And Not boolErrorDetected And Not boolShutDown ' subSend commands 
                        evntRccDataWaitingToSend.WaitOne(1000)
                        evntRccDataWaitingToSend.Reset()
                        If booRccDataWaitingToSend And Not boolErrorDetected And Not boolShutDown Then
                            booRccDataWaitingToSend = False
                            subSend(RccClientSocket, strRccSendMessage)
                            If (intNoResponseCounter > 2) Then boolErrorDetected = True
                        End If
                        Thread.Sleep(10)
                        classRccClient.Connected = RccClientSocket.Connected
                    End While
                    subDisconnect(RccClientSocket)
                End While
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subMain :  " & ex.ToString)
                boolErrorDetected = True
            End Try
        End Sub 'subMain

        Private Sub subDisconnect(ByRef client As Socket)
            Try
                classRccClient.Connected = False
                intNoResponseCounter = 0
                Thread.Sleep(500)
                If (client IsNot Nothing) Then
                    If client.Connected Then
                        client.Shutdown(SocketShutdown.Both)
                        Thread.Sleep(500)
                        If client.Connected Then client.Disconnect(Not boolShutDown)
                        Thread.Sleep(500)
                    End If
                    classRccClient.Connected = client.Connected
                    client.Dispose()
                End If
                Thread.Sleep(500)
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subDisconnect :  " & ex.ToString)
                classRccClient.Connected = False
                boolErrorDetected = True
            End Try
        End Sub

        Private Shared Sub subConnectCallback(ByVal ar As IAsyncResult)
            Try
                If Not boolErrorDetected And Not boolShutDown And (ar IsNot Nothing) Then
                    Dim client As Socket = CType(ar.AsyncState, Socket) ' Retrieve the socket from the RccClientState object.
                    If (client IsNot Nothing) Then
                        If client.Connected And Not boolShutDown Then
                            client.EndConnect(ar) ' Complete the connection.
                            evntConnectDone.Set() ' Signal that the connection has been made.
                        End If
                        classRccClient.Connected = client.Connected
                    End If
                End If
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subConnectCallback :  " & ex.ToString)
                boolErrorDetected = True
                classRccClient.Connected = False
            End Try
        End Sub 'subConnectCallback


        Private Shared Sub subReceive(ByVal client As Socket)
            If classRccClient.Connected And Not boolShutDown And Not boolErrorDetected And (client IsNot Nothing) Then
                Try
                    Dim state As New typeSocketClass ' Create the state object
                    state.workSocket = client
                    ' Begin receiving the data from the remote device.
                    client.BeginReceive(state.byteReceiveBuffer, 0, typeSocketClass.BufferSize, 0, New AsyncCallback(AddressOf subReceiveCallback), state)
                    classRccClient.Connected = client.Connected
                Catch ex As Exception
                    frmDebug.subWriteLogs(" EXCEPTION In subReceive :  " & ex.ToString)
                    boolErrorDetected = True
                End Try
            End If
        End Sub 'subReceive


        Private Shared Sub subReceiveCallback(ByVal ar As IAsyncResult)
            Try
                If classRccClient.Connected And Not boolShutDown And Not boolErrorDetected And (ar IsNot Nothing) Then
                    Dim RccSocketClassInstance As typeSocketClass = CType(ar.AsyncState, typeSocketClass)
                    Dim RccClientSocket As Socket = RccSocketClassInstance.workSocket
                    Dim bytesRead As Integer = RccClientSocket.EndReceive(ar) ' Read data from the client socket.
                    If classRccClient.Connected And Not boolErrorDetected And bytesRead > 0 And Not boolShutDown _
                        And (RccClientSocket IsNot Nothing) Then ' There  might be more data, so store the data received so far.
                        If (RccSocketClassInstance.sbReceivedData.Length < (UBound(RccSocketClassInstance.byteReceiveBuffer) - bytesRead)) Then
                            RccSocketClassInstance.sbReceivedData.Append(Encoding.ASCII.GetString(RccSocketClassInstance.byteReceiveBuffer, 0, bytesRead) & " ")
                            RccSocketClassInstance.sbReceivedData.Append(" ")
                            If (strRccReceiveMessage.Length + bytesRead) < UBound(RccSocketClassInstance.byteReceiveBuffer) Then
                                strRccReceiveMessage &= RccSocketClassInstance.sbReceivedData.ToString() ' Throws exceptions - out of range
                            End If
                        End If
                        If strRccReceiveMessage.Length > 3 And boolWaitingForData Then
                            If CBool(InStr(strRccReceiveMessage, vbCr)) Then
                                evntRccDataReceived.Set() 'Signal the subMain thread to continue.
                                evntRccClientDataPassed.WaitOne(500) ' subWait for subMain thread to get the data
                                evntRccClientDataPassed.Reset()
                                RccSocketClassInstance.sbReceivedData.Clear()   'clear the buffer
                                strRccReceiveMessage = ""
                            End If
                        End If
                    End If
                    Thread.Sleep(15)
                    If classRccClient.Connected And Not boolShutDown And Not boolErrorDetected And (RccClientSocket IsNot Nothing) Then _
                        RccClientSocket.BeginReceive(RccSocketClassInstance.byteReceiveBuffer, 0, typeSocketClass.BufferSize, 0, New AsyncCallback(AddressOf subReceiveCallback), RccSocketClassInstance)
                    classRccClient.Connected = RccClientSocket.Connected
                Else
                    boolErrorDetected = True
                End If 'If classRccClient.Connected
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subReceiveCallback :  " & ex.ToString)
                boolErrorDetected = True
            End Try
        End Sub 'subReadCallback

        Private Sub subSend(ByVal RccClientSocket As Socket, ByVal strMessage As String)
            Try
                ' Convert the string strMessage to byte strMessage using ASCII encoding.
                Dim bytestrMessage As Byte() = Encoding.ASCII.GetBytes(strMessage)
                ' Begin sending strMessage to Rcc.
                Try
                    If classRccClient.Connected And Not boolErrorDetected And Not boolShutDown And (RccClientSocket IsNot Nothing) Then _
                      RccClientSocket.BeginSend(bytestrMessage, 0, bytestrMessage.Length, 0, New AsyncCallback(AddressOf subSendCallback), RccClientSocket)
                    classRccClient.Connected = RccClientSocket.Connected
                Catch ex As Exception
                    boolErrorDetected = True
                End Try

                evntRccDataSent.WaitOne(300)
                evntRccDataSent.Reset()
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subSend :  " & ex.ToString)
                boolErrorDetected = True
            End Try
        End Sub 'subSend


        Private Sub subSendCallback(ByVal ar As IAsyncResult)
            Try
                If classRccClient.Connected And Not boolErrorDetected And Not boolShutDown And (ar IsNot Nothing) Then
                    Dim RccClientSocket As Socket = CType(ar.AsyncState, Socket) ' Retrieve the socket from the RccSocketClassInstance object.
                    evntRccDataSent.Set()
                End If
            Catch ex As Exception
                frmDebug.subWriteLogs(" EXCEPTION In subSendCallback :  " & ex.ToString)
                evntRccDataSent.Set()
                boolErrorDetected = True
            End Try
        End Sub 'subSendCallback

    End Class 'RccClientServerClass

#End Region




End Module
