Imports VB = Microsoft.VisualBasic



Public Class ER750Lib
    Inherits Device

    Private WithEvents _udp As UdpSocket
    Private WithEvents _tcpServer As New TCPServerSocket
    Private WithEvents _tcpClient As New TCPClientSocket

    Public Event EventMessage(ByVal source As String, _
                              ByVal eventMessage As String)
    Public Event ReceivedData(ByVal remoteIpAddress As String, _
                              ByVal remotePort As Integer, _
                              ByVal dataByteArray As Byte())
    Public Event ReceivedDeviceStatus(ByRef deviceStatus As Parameters.DeviceStatusFormat)
    Public Event ReceivedEventData(ByVal deviceIP As String,
                                   ByRef eventData As Parameters.EventDataFormat)
    Public Event ReceivedReplyCommand(ByVal remoteIpaddress As String,
                                      ByVal result As Devices.ER750.E_ErrorCodes)

    Public Event ErrorOccured(ByVal source As String, _
                              ByVal errorMessage As String)

    Private _batchJobs As New Queue(Of JobFormat)
    Private _broadcastDeviceIPCollection As New Collection


    Public Sub Broadcast()
        'Broadcast command
        Dim dataBytes() As Byte = {&HFF, &H4, &H2, &HFB}
        Dim i As Integer

        Try
            If _udp IsNot Nothing Then
                _udp = Nothing
            End If
            _udp = New UdpSocket

            _broadcastDeviceIPCollection.Clear()
            _udp.Bind("", 0)
            For i = 0 To 5
                _udp.Send("255.255.255.255", 23, dataBytes)
            Next
        Catch ex As Exception
            RaiseEvent EventMessage("Broascast", ex.Message)
        End Try
    End Sub


    Public Sub Broadcast(ByVal bindLocalIP As String)
        'Broadcast command
        Dim dataBytes() As Byte = {&HFF, &H4, &H2, &HFB}
        Dim i As Integer

        Try
            If _udp IsNot Nothing Then
                _udp = Nothing
            End If
            _udp = New UdpSocket

            _broadcastDeviceIPCollection.Clear()
            _udp.Bind(bindLocalIP, 0)

            For i = 0 To 5
                _udp.Send("255.255.255.255", 23, dataBytes)
            Next
        Catch ex As Exception
            RaiseEvent EventMessage("Broascast", ex.Message)
        End Try
    End Sub

    Public Sub StopListen()
        _tcpServer.StopListen()
    End Sub

    Public Sub StartListen(ByVal localIP As String, _
                           ByVal localPort As Integer)
        _tcpServer.StartListen(localIP, localPort)
    End Sub

    Public Sub StartListen(ByVal localIP As String)
        _tcpServer.StartListen(localIP, 2168)
    End Sub


    Public Overrides Sub Close()
        _udp.CloseConnection()
    End Sub

    Public Overloads Overrides Sub Open()

    End Sub

    Public Overloads Overrides Sub Open(ByVal connectionString As String)

    End Sub

    Public Overrides Property Retries() As Integer
        Get
            Return _retries
        End Get
        Set(ByVal value As Integer)
            _retries = value
        End Set
    End Property

    Public Overrides Property Timeout() As Integer
        Get
            Return _timeout
        End Get
        Set(ByVal value As Integer)
            _timeout = value
        End Set
    End Property

    Private Sub _udp_DataReceived(ByVal remoteIP As String, _
                                  ByVal remotePort As Integer, _
                                  ByRef dataByte() As Byte) Handles _udp.DataReceived
        RaiseEvent ReceivedData(remoteIP, remotePort, dataByte)

        Dim deviceState As New Parameters.DeviceStatusFormat

        deviceState.ParseParameter(dataByte)

        If deviceState.ErrorCode = E_ErrorCodes.E00_Success Then
            Try
                _broadcastDeviceIPCollection.Add(deviceState.IpAddress, deviceState.IpAddress)
                RaiseEvent ReceivedDeviceStatus(deviceState)
            Catch ex As Exception
                'duplicated IP address, 
                'do nothing here
            End Try
        Else
            RaiseEvent EventMessage(remoteIP, "Cannot parse device status")
        End If
    End Sub

    Public Sub GetLocalIP(ByRef localIpCount As Integer,
                          ByRef localIPs() As String)
        If _udp Is Nothing Then
            _udp = New UdpSocket
        End If

        _udp.GetLocalIP(localIPs)

        If localIPs Is Nothing Then
            localIpCount = 0
        Else
            localIpCount = localIPs.Length
        End If

    End Sub

    Private Sub _tcpServer_Connected(ByVal remoteIP As String, ByVal remotePort As Integer) Handles _tcpServer.Connected
        RaiseEvent EventMessage(remoteIP, "Connected (Server Socket)")
    End Sub


    Private Sub _tcpServer_DataReceived(ByVal clientIP As String, _
                                        ByVal remotePort As Integer, _
                                        ByRef dataByte() As Byte) Handles _tcpServer.DataReceived
        Dim eventData As New GIGATMS.Devices.ER750.Parameters.EventDataFormat

        Try
            eventData.ParseParameter(dataByte)

            RaiseEvent ReceivedEventData(clientIP, eventData)
        Catch ex As Exception
            RaiseEvent EventMessage(clientIP, "Cannot parse Event Data")
        End Try



    End Sub


    Public Sub ConnectToReader(ByVal remoteIP As String, _
                               ByVal remotePort As Integer)
        _tcpClient.Connect(remoteIP, remotePort)
    End Sub


    Public Sub ConnectToReader(ByVal remoteIP As String)
        _tcpClient.Connect(remoteIP, 2167)
    End Sub

    Public Sub SendOpenDoorCommand(ByVal duration As Byte)
        Dim gnet As New GnetCommandFormat
        Dim parameterByteArray(1) As Byte
        Dim commandByteArray() As Byte

        parameterByteArray(0) = 0
        parameterByteArray(1) = duration
        commandByteArray = gnet.GetPackageCommand(0, &H11, parameterByteArray)

        Try
            _tcpClient.Send(commandByteArray)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub


    'This command (ControlLedBuzzer) doesn't use GNet command format
    Private Sub SendControlLedBuzzerCommand(ByVal controlLedBuzzerSelection As Byte)
        Dim commandByteArray(4) As Byte

        commandByteArray(0) = 2
        commandByteArray(1) = &H4A
        commandByteArray(2) = &H30 + controlLedBuzzerSelection
        commandByteArray(3) = &HD

        Try
            _tcpClient.Send(commandByteArray)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try


    End Sub

    'for TCPClient Only
    Private Sub DoNextJobs()
        Dim job As JobFormat
        Dim col() As String
        Dim integerParameter As Integer

        If _batchJobs.Count > 0 Then
            job = _batchJobs.Dequeue

            Select Case job.Job
                Case E_Jobs.E00_ConnectToReader
                    col = Split(job.Parameter, ":")
                    ConnectToReader(col(0), Val(col(1)))
                Case E_Jobs.E01_SendOpenDoorCommand
                    integerParameter = job.Parameter
                    SendOpenDoorCommand(integerParameter)
                Case E_Jobs.E02_SendControlLedBuzzerCommand
                    integerParameter = job.Parameter
                    SendControlLedBuzzerCommand(integerParameter)
                Case E_Jobs.E98_Disconnect
                    _tcpClient.CloseConnection()
                Case E_Jobs.E99_Complete
                    CompleteJob()
                Case Else
                    RaiseEvent EventMessage("DoNextJob", "Unknown job")
            End Select

        Else
            'RaiseEvent EventMessage("DoNextJob", "No job to do")
        End If
    End Sub

    Public Sub CompleteJob()
        _batchJobs.Clear()
        RaiseEvent EventMessage(_tcpClient.RemoteIP, "Completed")
    End Sub

    Public Sub OpenDoor(ByVal remoteIP As String,
                        ByVal remotePort As Integer,
                        ByVal duration As Byte)
        _batchJobs.Clear()

        If _tcpClient.IsConnected Then
            _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        End If

        _batchJobs.Enqueue(New JobFormat(E_Jobs.E00_ConnectToReader, remoteIP & ":" & remotePort.ToString))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E01_SendOpenDoorCommand, duration))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E99_Complete))

        DoNextJobs()
    End Sub

    Public Sub OpenDoor(ByVal remoteIP As String,
                        ByVal remotePort As Integer,
                        ByVal duration As Byte,
                        ByVal closeConnection As Boolean)
        _batchJobs.Clear()

        If _tcpClient.IsConnected Then
            _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        End If

        _batchJobs.Enqueue(New JobFormat(E_Jobs.E00_ConnectToReader, remoteIP & ":" & remotePort.ToString))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E01_SendOpenDoorCommand, duration))

        If closeConnection = True Then
            _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        End If

        _batchJobs.Enqueue(New JobFormat(E_Jobs.E99_Complete))

        DoNextJobs()
    End Sub

    Public Sub ControlLedBuzzer(ByVal remoteIP As String,
                                ByVal remotePort As Integer,
                                ByVal controlLedBuzzerSelection As Byte)
        _batchJobs.Clear()

        If _tcpClient.IsConnected Then
            _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        End If

        _batchJobs.Enqueue(New JobFormat(E_Jobs.E00_ConnectToReader, remoteIP & ":" & remotePort.ToString))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E02_SendControlLedBuzzerCommand, controlLedBuzzerSelection))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E99_Complete))

        DoNextJobs()
    End Sub

    Public Sub ControlLedBuzzer(ByVal remoteIP As String,
                                ByVal remotePort As Integer,
                                ByVal controlLedBuzzerSelection As Byte,
                                ByVal establishConnection As Boolean)
        _batchJobs.Clear()

        If establishConnection = True Then
            If _tcpClient.IsConnected Then
                _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
            End If

            _batchJobs.Enqueue(New JobFormat(E_Jobs.E00_ConnectToReader, remoteIP & ":" & remotePort.ToString))
        End If

        _batchJobs.Enqueue(New JobFormat(E_Jobs.E02_SendControlLedBuzzerCommand, controlLedBuzzerSelection))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E98_Disconnect))
        _batchJobs.Enqueue(New JobFormat(E_Jobs.E99_Complete))

        DoNextJobs()
    End Sub

    Private Sub _tcpClient_Connected() Handles _tcpClient.Connected
        RaiseEvent EventMessage(_tcpClient.RemoteIP, "Connected (Client Socket)")
        DoNextJobs()
    End Sub

    Private Sub _tcpClient_DataReceived(ByRef dataByte() As Byte) Handles _tcpClient.DataReceived
        Dim cmd As New GnetCommandFormat

        Try
            If dataByte.Length = 1 Then
                If dataByte(0) = &H6 Then
                    'The reply command is for the request of control Led/Buzzer command
                    RaiseEvent EventMessage(_tcpClient.RemoteIP, "Received: " & "E00_Success")
                    RaiseEvent ReceivedReplyCommand(_tcpClient.RemoteIP,
                                                    E_ErrorCodes.E00_Success)
                Else
                    RaiseEvent ErrorOccured(_tcpClient.RemoteIP, "_tcpClient_DataReceived: " & "Unknown reply command")
                    RaiseEvent ReceivedReplyCommand(_tcpClient.RemoteIP,
                                                    E_ErrorCodes.E01_Failed)
                End If
            Else
                cmd.ParseGnetCommand(dataByte)
                RaiseEvent EventMessage(_tcpClient.RemoteIP, "Received: " & cmd.ErrorCode.ToString)

                If cmd.ErrorCode = E_GnetErrorCodes.E00_Success Then
                    RaiseEvent ReceivedReplyCommand(_tcpClient.RemoteIP,
                                                    E_ErrorCodes.E00_Success)
                Else
                    RaiseEvent ErrorOccured(_tcpClient.RemoteIP, "_tcpClient_DataReceived: " & cmd.ErrorCode.ToString)
                    RaiseEvent ReceivedReplyCommand(_tcpClient.RemoteIP,
                                                    E_ErrorCodes.E01_Failed)
                End If

            End If


            DoNextJobs()
        Catch ex As Exception
            RaiseEvent EventMessage(_tcpClient.RemoteIP, ex.Message)
            _batchJobs.Clear()
            RaiseEvent ErrorOccured(_tcpClient.RemoteIP, ex.Message)
        End Try

    End Sub

    Private Sub _tcpClient_Disconnected() Handles _tcpClient.Disconnected
        RaiseEvent EventMessage(_tcpClient.RemoteIP, "Disconnected (Client Socket)")
        DoNextJobs()
    End Sub

    Private Sub _tcpServer_Disconnected(ByVal remoteIP As String, ByVal remotePort As Integer) Handles _tcpServer.Disconnected
        RaiseEvent EventMessage(remoteIP, "Disconnected (Server Socket)")
    End Sub

    Private Sub _tcpClient_ErrorOccurred(ByVal errorMessage As String) Handles _tcpClient.ErrorOccurred
        RaiseEvent ErrorOccured(_tcpClient.RemoteIP, errorMessage)
    End Sub

    Private Sub _tcpClient_SendComplete(ByVal bytesSent As Integer) Handles _tcpClient.SendComplete
        RaiseEvent EventMessage(_tcpClient.RemoteIP, "Command sent")
    End Sub
End Class
