Imports System.Drawing
'****************************************************************************
'* 12-DEC-08 Added line in OnPaint to exit is LegendText is nothing
'* 05-OCT-09 Exit OnPaint if GrayPen is Nothing
'****************************************************************************
Public Class BasicLight
    Inherits MfgControl.AdvancedHMI.Controls.Indicator

#Region "Basic Properties"
    '* This is necessary to make the background draw correctly
    '*  http://www.bobpowell.net/transcontrols.htm
    '*part of the transparent background code
    Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
        Get
            Dim cp As System.Windows.Forms.CreateParams = MyBase.CreateParams
            cp.ExStyle = cp.ExStyle Or 32
            Return cp
            'Return MyBase.CreateParams
        End Get
    End Property
#End Region

#Region "PLC Related Properties"
    '*****************************************************
    '* Property - Component to communicate to PLC through
    '*****************************************************
    Private _CommComponent As ICommComponent
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property CommComponent() As ICommComponent
        Get
            Return _CommComponent
        End Get
        Set(ByVal value As ICommComponent)
            _CommComponent = value
        End Set
    End Property

    '*************************************************************
    '* Property - Address in PLC to Link to for selecting color 2
    '*************************************************************
    Private NotificationIDSelectColor2 As Integer
    Private m_PLCaddressSelectColor2 As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressSelectColor2() As String
        Get
            Return m_PLCaddressSelectColor2
        End Get
        Set(ByVal value As String)
            If m_PLCaddressSelectColor2 <> value Then
                m_PLCaddressSelectColor2 = value
                SubscribeToCommDriver()
            End If
        End Set
    End Property

    '*************************************************************
    '* Property - Address in PLC to Link to for selecting color 3
    '*************************************************************
    Private NotificationIDSelectColor3 As Integer
    Private m_PLCaddressSelectColor3 As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressSelectColor3() As String
        Get
            Return m_PLCaddressSelectColor3
        End Get
        Set(ByVal value As String)
            If m_PLCaddressSelectColor3 <> value Then
                m_PLCaddressSelectColor3 = value
                SubscribeToCommDriver()
            End If
        End Set
    End Property

    '*****************************************
    '* Property - Address in PLC to Link to
    '*****************************************
    Private NotificationIDText As Integer
    Private m_PLCaddressText As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressText() As String
        Get
            Return m_PLCaddressText
        End Get
        Set(ByVal value As String)
            If m_PLCaddressText <> value Then
                m_PLCaddressText = value

                '* When address is changed, re-subscribe to new address
                SubscribeToCommDriver()
            End If
        End Set
    End Property

    '*****************************************
    '* Property - Address in PLC to Link to
    '*****************************************
    Private NotificationIDVisibility As Integer
    Private m_PLCaddressVisibility As String = ""
    <System.ComponentModel.Category("PLC Properties")> _
    Public Property PLCaddressVisibility() As String
        Get
            Return m_PLCaddressVisibility
        End Get
        Set(ByVal value As String)
            If m_PLCaddressVisibility <> value Then
                m_PLCaddressVisibility = value
                SubscribeToCommDriver()
            End If
        End Set
    End Property
#End Region

#Region "Events"
    '****************************************************************
    '* UserControl overrides dispose to clean up the component list.
    '****************************************************************
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing And _CommComponent IsNot Nothing Then
                _CommComponent.UnSubscribe(NotificationIDSelectColor2)
                _CommComponent.UnSubscribe(NotificationIDSelectColor3)
                _CommComponent.UnSubscribe(NotificationIDText)
                _CommComponent.UnSubscribe(NotificationIDVisibility)
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    '* This is part of the transparent background code and it stops flicker
    'Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
    '    'MyBase.OnPaintBackground(e)
    'End Sub


    '********************************************************************
    '* When an instance is added to the form, set the comm component
    '* property. If a comm component does not exist, add one to the form
    '********************************************************************
    Protected Overrides Sub OnCreateControl()
        MyBase.OnCreateControl()

        If Me.DesignMode Then
            'If Me Is Nothing OrElse Me.Parent Is Nothing OrElse Me.Parent.Site Is Nothing Then Exit Sub

            '********************************************************
            '* Search for ICommComponent component in parent form
            '* If one exists, set the client of this component to it
            '********************************************************
            Dim i = 0
            Dim j As Integer = Me.Parent.Site.Container.Components.Count - 1
            While _CommComponent Is Nothing And i < j
                If Me.Parent.Site.Container.Components(i).GetType.GetInterface("ICommComponent") IsNot Nothing Then _CommComponent = Me.Parent.Site.Container.Components(i)
                i += 1
            End While

            '************************************************
            '* If no comm component was found, then add one and
            '* point the CommComponent property to it
            '*********************************************
            If _CommComponent Is Nothing Then
                Me.Parent.Site.Container.Add(New TwinCATComm)
                _CommComponent = Me.Parent.Site.Container.Components(Me.Parent.Site.Container.Components.Count - 1)
            End If
        Else
            SubscribeToCommDriver()
        End If
    End Sub
#End Region


#Region "Subscribing and PLC data receiving"
    '**************************************************
    '* Subscribe to addresses in the Comm(PLC) Driver
    '**************************************************
    Private SubscribedPLCAddressSelectColor2 As String
    Private SubscribedPLCAddressSelectColor3 As String
    Private SubscribedPLCAddressText As String
    Private SubscribedPLCAddressVisibility As String
    Private Sub SubscribeToCommDriver()
        If Not DesignMode And IsHandleCreated Then
            '*************************
            '* Select Color1 Subscription
            '*************************
            If SubscribedPLCAddressSelectColor2 <> m_PLCaddressSelectColor2 Then
                '* If already subscribed, but address is changed, then unsubscribe first
                If NotificationIDSelectColor2 > 0 Then
                    _CommComponent.UnSubscribe(NotificationIDSelectColor2)
                End If
                '* Is there an address to subscribe to?
                If m_PLCaddressSelectColor2 <> "" Then
                    Try
                        If _CommComponent IsNot Nothing Then
                            NotificationIDSelectColor2 = _CommComponent.Subscribe(m_PLCaddressSelectColor2, 250, AddressOf PolledDataReturnedSelectColor2)

                            '* If subscription succeedded, save the address
                            SubscribedPLCAddressSelectColor2 = m_PLCaddressSelectColor2
                        Else
                            DisplayError("CommComponent Property not set")
                        End If
                    Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                        '* If subscribe failes, set up for retry
                        InitializeSubscribeRetry(ex, m_PLCaddressSelectColor2)
                    End Try
                End If
            End If

            '*****************************
            '* Select Color3 Subscription
            '****************************
            If SubscribedPLCAddressSelectColor3 <> m_PLCaddressSelectColor3 Then
                '* If already subscribed, but address is changed, then unsubscribe first
                If NotificationIDSelectColor3 > 0 Then
                    _CommComponent.UnSubscribe(NotificationIDSelectColor3)
                End If
                '* Is there an address to subscribe to?
                If m_PLCaddressSelectColor3 <> "" Then
                    Try
                        If _CommComponent IsNot Nothing Then
                            NotificationIDSelectColor3 = _CommComponent.Subscribe(m_PLCaddressSelectColor3, 250, AddressOf PolledDataReturnedSelectColor3)

                            '* If subscription succeedded, save the address
                            SubscribedPLCAddressSelectColor3 = m_PLCaddressSelectColor3
                        Else
                            DisplayError("CommComponent Property not set")
                        End If
                    Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                        '* If subscribe failes, set up for retry
                        InitializeSubscribeRetry(ex, m_PLCaddressSelectColor3)
                    End Try
                End If
            End If

            '*************************
            '* Text Subscription
            '*************************
            If SubscribedPLCAddressText <> m_PLCaddressText Then
                '* If already subscribed, but address is changed, then unsubscribe first
                If NotificationIDText > 0 Then
                    _CommComponent.UnSubscribe(NotificationIDText)
                End If
                '* Is there an address to subscribe to?
                If m_PLCaddressText <> "" Then
                    Try
                        If _CommComponent IsNot Nothing Then
                            NotificationIDText = _CommComponent.Subscribe(m_PLCaddressText, 250, AddressOf PolledDataReturnedText)

                            '* If subscription succeedded, save the address
                            SubscribedPLCAddressText = m_PLCaddressText
                        Else
                            DisplayError("CommComponent Property not set")
                        End If
                    Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                        '* If subscribe fails, set up for retry
                        InitializeSubscribeRetry(ex, m_PLCaddressText)
                    End Try
                End If
            End If

            '*************************
            '* Visbility Subscription
            '*************************
            If SubscribedPLCAddressVisibility <> m_PLCaddressVisibility Then
                '* If already subscribed, but address is changed, then unsubscribe first
                If NotificationIDVisibility > 0 Then
                    _CommComponent.UnSubscribe(NotificationIDVisibility)
                End If
                '* Is there an address to subscribe to?
                If m_PLCaddressVisibility <> "" Then
                    Try
                        If _CommComponent IsNot Nothing Then
                            NotificationIDVisibility = _CommComponent.Subscribe(m_PLCaddressVisibility, 250, AddressOf PolledDataReturnedVisibility)

                            SubscribedPLCAddressVisibility = m_PLCaddressVisibility
                        Else
                            DisplayError("CommComponent Property not set")
                        End If
                    Catch ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException
                        '* If subscribe fails, set up for retry
                        InitializeSubscribeRetry(ex, m_PLCaddressVisibility)
                    End Try
                End If
            End If
        End If
    End Sub

    '********************************************
    '* Show the error and start the retry time
    '********************************************
    Private Sub InitializeSubscribeRetry(ByVal ex As MfgControl.AdvancedHMI.Drivers.PLCDriverException, ByVal PLCAddress As String)
        If ex.ErrorCode = 1808 Then
            DisplayError("""" & PLCAddress & """ PLC Address not found")
        Else
            DisplayError(ex.Message)
        End If

        If SubscribeRetryTimer Is Nothing Then
            SubscribeRetryTimer = New Windows.Forms.Timer
            SubscribeRetryTimer.Interval = 10000
            AddHandler SubscribeRetryTimer.Tick, AddressOf Retry_Tick
        End If

        SubscribeRetryTimer.Enabled = True
    End Sub


    '********************************************
    '* Keep retrying to subscribe if it failed
    '********************************************
    Private SubscribeRetryTimer As Windows.Forms.Timer
    Private Sub Retry_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        SubscribeRetryTimer.Enabled = False
        SubscribeRetryTimer.Dispose()
        SubscribeRetryTimer = Nothing

        SubscribeToCommDriver()
    End Sub


    '***************************************
    '* Call backs for returned data
    '***************************************
    Private OriginalText As String

    Private Sub PolledDataReturnedSelectColor2(ByVal Values() As String)
        Try
            SelectColor2 = Values(0)
        Catch
            DisplayError("INVALID SelectColor2 Value RETURNED!")
        End Try
    End Sub

    Private Sub PolledDataReturnedSelectColor3(ByVal Values() As String)
        Try
            SelectColor3 = Values(0)
        Catch
            DisplayError("INVALID SelectColor3 VALUE RETURNED!")
        End Try
    End Sub

    Private Sub PolledDataReturnedText(ByVal Values() As String)
        Try
            MyBase.Text = Values(0)
        Catch
            DisplayError("INVALID VALUE RETURNED!")
        End Try
    End Sub


    Private Sub PolledDataReturnedVisibility(ByVal Values() As String)
        Try
            MyBase.Visible = Values(0)
        Catch
            DisplayError("INVALID Visibilty VALUE RETURNED!")
        End Try
    End Sub
#End Region

#Region "Error Display"
    '********************************************************
    '* Show an error via the text property for a short time
    '********************************************************
    Private WithEvents ErrorDisplayTime As System.Windows.Forms.Timer
    Private Sub DisplayError(ByVal ErrorMessage As String)
        If ErrorDisplayTime Is Nothing Then
            ErrorDisplayTime = New System.Windows.Forms.Timer
            AddHandler ErrorDisplayTime.Tick, AddressOf ErrorDisplay_Tick
            ErrorDisplayTime.Interval = 5000
        End If

        '* Save the text to return to
        If Not ErrorDisplayTime.Enabled Then
            OriginalText = Me.Text
        End If

        ErrorDisplayTime.Enabled = True

        Me.Text = ErrorMessage
    End Sub


    '**************************************************************************************
    '* Return the text back to its original after displaying the error for a few seconds.
    '**************************************************************************************
    Private Sub ErrorDisplay_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Text = OriginalText

        If ErrorDisplayTime IsNot Nothing Then
            ErrorDisplayTime.Enabled = False
            ErrorDisplayTime.Dispose()
            ErrorDisplayTime = Nothing
        End If
    End Sub
#End Region
End Class

