Imports System.Threading
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Speech
Imports System.IO

Public Class Form_Dome
    Dim tcpClient As New System.Net.Sockets.TcpClient()
    Dim networkStream As NetworkStream
    Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes("Request Dome Controller IP")
    Dim IPaddr As IPAddress
    Dim IPaddrUDP As IPAddress
    Dim SetIPaddr As IPAddress
    Dim UDPnetwork As String
    Const UDPremote As Integer = 7778
    Const UDPlocalSend As Integer = 7775
    Const UDPlocalReceive As Integer = 7776
    Dim UDPlistenPort As Integer = UDPremote
    Dim UDPsendPort As Integer = UDPremote
    Dim TCPdataPort As Integer = 7777
    Public AGFipAddress As String
    Dim AGFtimeoutTCP As Integer
    Public SocketIsOpen As Boolean = False
    Dim TBmountAz As String = "Mount Az = "
    Dim TBdomeAz As String = "Current Az = "
    Dim TBmoveAz As String
    Public FormLoading As Boolean = True
    Dim DomeCalcGood As Boolean = False
    Dim AP_AZ As String
    Dim AP_AL As String
    Dim Lat As String = ""
    Dim DomeAz As Double
    Dim DomeCurAz As Integer
    Dim DomeCalcAz As Integer = -1
    Dim ScopeCurAz As Integer
    Dim ScopeSaveAz As Integer = -1
    Dim ScopeCurPos As Integer
    Dim ScopeSavePos As Integer = -1
    Dim MonitorCmdSave As Boolean
    Dim DomeImage As Image
    Dim DomeRotate As Integer = 0
    Dim DomeAGFstop As String = ""
    Dim DomeStartPosAGF As Integer
    Dim DomeDirectionAGF As Integer
    Dim DomeMovingAGF As Boolean = False
    Public DebugLog As Boolean
    Dim SRA, SAL, SAZ, SST As String

    Const CtlNCO As Integer = 0
    Public Const CtlAGF As Integer = 1
    Const CtlNone As Integer = -1
    Public CtlType As Integer
    Dim ActiveCtl As Integer = CtlNone
    Dim AGFnetwork As Boolean = False

    Dim TimeStart, TimeEnd As Single
    Dim TimeOfMove As Single
    Dim DegOfMove As Single

    Private WithEvents UDPWorker As System.ComponentModel.BackgroundWorker

    Public DataReceived As String
    Public Active As Boolean = False
    Dim ReceiveEx As String
    Private udpClient As New Net.Sockets.UdpClient()
    Public RemoteIP As String = ""
    Public DomeTest As Integer = 0
    Public DomeResponse As String = ""
    Dim HelpResponse As String
    Dim DomeSent As String = "none"
    Dim DomeStatus As String = "none"
    Dim MoveDome As Boolean = False
    Dim MoveError As Boolean = False
    Dim PollIndex As Integer = 0
    Dim PollMax As Integer = 3
    Dim Url0 As String
    Dim T As String
    Dim Talker As New Speech.Synthesis.SpeechSynthesizer
    Dim DSRswitch As Boolean = False
    Dim DSRswitchLast As Integer = -2
    Dim DSRstart As Boolean = False
    Public DSRstate As Integer = -2
    Dim AGFtimedmove As Boolean = False
    Dim DSRswitchset As Boolean
    Dim SigPin As Integer = 0
    Dim SigPinPrev As Integer = -1
    Dim CTSstate As Integer = -2
    Dim CTSstateLast As Integer = -1
    Dim PinChangedEntered As Boolean = False
    Dim LastPinChange As Integer = -2
    Dim TrackDotCount As Integer
    Public ParkPos As String
    Dim PrevStatus As String = ""
    Dim PrevRecvNCO As String = ""
    Dim PrevSentNCO As String = ""
    Dim AGFcomDiagLen As Integer
    Dim NCO_Do_INIT As Boolean = False
    Public AutoDomeTrackStarting As Boolean
    Dim TimerDSRignore As Boolean = False
    Dim ComBreakIssued As Boolean = False
    Dim BreakTypeClose As Boolean = True
    Dim DupLogCheck As Boolean = False
    Dim BreakChars As Integer = 0
    Dim EWswCP3MeridianDelay As Boolean = False
    Dim AGFcal As Boolean = False
    Dim AGFcalDir As Integer = 0
    Dim AGFsecdeg As Integer
    Dim BegCalAGF As TimeSpan
    Dim EndCalAGF As TimeSpan
    Dim DSRportName As String
    Dim FirstBreak As Boolean = False
    Dim MerFmt As String = ""
    Dim MoveDomeTimeSec As Single
    Dim AGFdebugPortName As String
    Dim AGFdebugData As String
    Dim AGFdomeDebugMove As Integer
    Public DomeConnected As Boolean = False
    Dim FormIsShrunk As Boolean = False
    Dim TestDC As Boolean = False
    Dim DomeCalcAzN As Integer
    Dim AGFarduino As Boolean = False
    Dim TimerDSRcount As Integer = 0
    Dim AZdeg As String = ""
    Dim AZmin As String = ""
    Dim AZsec As String = ""

    ' AP 900 mount parameters
    Public MountD As Double = 280
    Public Xla As Double = -120.0
    Public Yla As Double = 0.0
    Public Zla As Double = 100.0

Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            Const CS_DBLCLKS As Int32 = &H8
            Const CS_NOCLOSE As Int32 = &H200
            cp.ClassStyle = CS_DBLCLKS Or CS_NOCLOSE
            Return cp
        End Get
    End Property

    Private Sub Form_Dome_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' Make sure form is on the screen
        If Me.Location.X < 0 Or Me.Location.Y < 0 Then
            Me.Location = New Point(0, 0)
        End If

        If Form1.DomeH >= 200 Then
            Me.Height = Form1.DomeH
        End If
        If Form1.DomeW >= 200 Then
            Me.Width = Form1.DomeW
        End If

        FormLoading = True
        Talker.Rate = Form_ControlP.ComboBoxSpeakRate.SelectedItem
        LabelDsr.Text = ""
        TBmoveAz = LabelTmove.Text & " = "
        LabelTmove.Text = TBmoveAz & TrackBarDome.Value

        If RemoteIP <> "" Then
            LabelRemoteIP.Text = RemoteIP
            ButtonDomeConnect.Enabled = True
        End If

        ' save picture of dome in form so can rotate it later
        ImageList1.Images.Add(My.Resources.Dome2)
        DomeImage = ImageList1.Images(0)
        PictureBoxDome.Refresh()

        ' polling indicators
        ImageList2.Images.Add(My.Resources.Ind1)
        ImageList2.Images.Add(My.Resources.Ind2)
        ImageList2.Images.Add(My.Resources.Ind3)
        ImageList2.Images.Add(My.Resources.Ind4)
        PictureBoxInd.Visible = False

        ' controller type selected
        CtlType = TabControl1.SelectedIndex

        SetUDPnetwork(DomeTest)

        ' dsr manual switch        
        ConnectDSRport.Checked = My.Settings.TrackingDSR
        GetDSRcheckState()
        If ConnectDSRport.Checked = True Then
            UpdateStatusLine("Monitoring DSR port, " & SerialPort3.PortName, Color.Black)
            Dim Dstate As String = "False"
            If SerialPort3.DsrHolding = True Then
                Dstate = "True"
            End If
            UpdateStatusLine("DSR switch set to " & Dstate, Color.Black)
        End If

        ' set EW switch does pier side option
        EWswCP3MeridianDelay = ButtonEWSwitchDoesCP3MeridianDelay.Checked
        Form1.EWswitchCP3MeridianDelay = ButtonEWSwitchDoesCP3MeridianDelay.Checked

        ' Make sure window is not off of screen
        If Me.Left + Me.Width > Form1.ScreenWidth Then
            Me.Left = Form1.ScreenWidth - Me.Width - 100
        End If
        If Me.Top + Me.Height > Form1.ScreenHeight Then
            Me.Top = Form1.ScreenHeight - Me.Height - 100
        End If

        FormLoading = False

    End Sub

    Private Sub Form_Dome_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If SocketIsOpen = True Then
            tcpClient.Close()
            SocketIsOpen = False
        End If

    End Sub

    Private Sub SetUDPnetwork(ByVal net As Integer)
        UDPlistenPort = UDPremote
        UDPsendPort = UDPremote
        UseLocalhostToLocateDomeControllerEmulatorToolStripMenuItem.Checked = False
        UseNetworkMaskBelowToLocateDomeControllerToolStripMenuItem.Checked = False
        UseRemoteNetworkToLocateDomeControllerEmulatorToolStripMenuItem.Checked = False

        Select Case net
            Case 1
                UseLocalhostToLocateDomeControllerEmulatorToolStripMenuItem.Checked = True
                UDPnetwork = "127.0.0.255"
                UDPlistenPort = UDPlocalReceive
                UDPsendPort = UDPlocalSend
            Case 3
                UseNetworkMaskBelowToLocateDomeControllerToolStripMenuItem.Checked = True
                UDPnetwork = ToolStripTextBoxMask.Text
            Case 4
                UseRemoteNetworkToLocateDomeControllerEmulatorToolStripMenuItem.Checked = True
                UDPnetwork = "255.255.255.255"
                UDPlistenPort = UDPlocalReceive
                UDPsendPort = UDPlocalSend
            Case Else
                UDPnetwork = "255.255.255.255"
        End Select
        LabelNet.Text = UDPnetwork
        UpdateStatusLine("NCO locate network set to " & UDPnetwork, Color.Black)
        DomeTest = net

    End Sub

    Private Sub ButtonClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonClose.Click
        CloseDome()

    End Sub

    Public Sub CloseDome()
        If FormIsShrunk = False Then
            Form1.DomeH = Me.Height
            Form1.DomeW = Me.Width
        End If
        Me.Hide()

    End Sub

    Private Sub ButtonGetAz_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGetAz.Click
        If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
            StatusLabel.Text = ""
            GetMountAZ()
            If SerialPort2.IsOpen = True Or SocketIsOpen = True Then
                ButtonDomeSync.Enabled = True
            Else
                ButtonDomeSync.Enabled = False
            End If
        End If

    End Sub

    Private Sub ButtonDomeConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeConnect.Click
        If SocketIsOpen = False Then
            Me.Cursor = Cursors.WaitCursor
            Try
                UpdateStatusLine("Connecting to Dome controller, 30 second timeout", Color.Black)
                Application.DoEvents()
                tcpClient = New System.Net.Sockets.TcpClient()
                IPaddr = IPAddress.Parse(RemoteIP)
                tcpClient.Connect(IPaddr, TCPdataPort)

                tcpClient.ReceiveTimeout = 3000
                networkStream = tcpClient.GetStream
                SocketIsOpen = True
                ButtonDomeConnect.Text = "Disconnect"
                ButtonAGFconnect.Enabled = False
                ButtonDomeGet.Enabled = True
                ButtonDomeGoto.Enabled = True
                ButtonDomeStop.Enabled = True
                ButtonDomeStatus.Enabled = True
                ButtonMoveCCW.Enabled = True
                ButtonMoveCW.Enabled = True
                ButtonDomeSync.Enabled = ButtonGetAz.Enabled
                CheckBoxTrack.Enabled = ButtonGetAz.Enabled
                Form1.CheckBoxDT.Enabled = CheckBoxTrack.Enabled
                ButtonLocate.Enabled = False
                Form_ControlP.ButtonDomeTest.Enabled = True
                PictureBoxInd.Visible = True
                UpdateStatusLine("Connected to Dome controller", Color.Black)
                If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
                    ButtonDC.Enabled = True
                    ButtonMoveDomeToCalc.Enabled = True
                    Form_ControlP.ButtonDomeTest.Enabled = True
                End If
                NCO_Do_INIT = True
                ActiveCtl = CtlNCO
                TimerDomeMove.Enabled = True
                ButtonGetAz.PerformClick()
                ButtonDC.PerformClick()
                DomeResponse = "Connected"
                DomeConnected = True

            Catch ex As Exception
                UpdateStatusLine("Connect error: '" & ex.Message & "'", Color.DarkRed)
            End Try

        Else

            tcpClient.Close()
            SocketIsOpen = False
            ButtonDomeConnect.Text = "Connect"
            ButtonAGFconnect.Enabled = True
            ButtonDomeGet.Enabled = False
            ButtonDomeGoto.Enabled = False
            ButtonDomeStop.Enabled = False
            ButtonDomeSync.Enabled = False
            CheckBoxTrack.Checked = False
            CheckBoxTrack.Enabled = False
            Form1.CheckBoxDT.Enabled = CheckBoxTrack.Enabled
            TimerTrack.Enabled = False
            ButtonDomeStatus.Enabled = False
            ButtonMoveCCW.Enabled = False
            ButtonMoveCW.Enabled = False
            ButtonLocate.Enabled = True
            Form_ControlP.ButtonDomeTest.Enabled = False
            PictureBoxInd.Visible = False
            UpdateStatusLine("Disconnected from Dome controller", Color.Black)
            ButtonDC.Enabled = False
            Form_ControlP.ButtonDomeTest.Enabled = False
            ButtonMoveDomeToCalc.Enabled = False
            TimerDomeMove.Enabled = False
            NCO_Do_INIT = False
            ActiveCtl = CtlNone
            DomeConnected = False
        End If

        Me.Cursor = Cursors.Default
        Application.DoEvents()

    End Sub

    Private Sub ButtonDomeGet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeGet.Click
        Dim I As Integer

        SendCommand("GETAZ")
        ' check for good response
        Try
            If Mid(DomeResponse, 1, 2) = "OK" And DomeResponse.Length > 5 Then
                I = Mid(DomeResponse, 4, 3)
                If I >= 0 Then
                    TrackBarDomePos.Value = I
                    DomeCurAz = I
                    DomeRotate = I
                    LabelTdome.Text = TBdomeAz & I
                    PictureBoxDome.Refresh()
                Else
                    If NCO_Do_INIT = True Then
                        SendDomeINITCommandToolStripMenuItem.PerformClick()
                    Else
                        UpdateStatusLine("Cannot get dome Az, send INIT command", Color.DarkRed)
                    End If
                    NCO_Do_INIT = False
                End If
            Else
                LabelTdome.Text = "Error"
            End If

        Catch ex As Exception
            UpdateStatusLine("'" & DomeResponse & "' GETAZ from dome controller exception, " & ex.Message, Color.DarkRed)

        End Try

    End Sub

    Private Sub PictureBoxDome_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBoxDome.Paint
        Dim Psize As Integer = 64 / 2
        Try
            With e.Graphics
                .TranslateTransform(Psize, Psize)
                .RotateTransform(DomeRotate)
                .DrawImage(DomeImage, Psize * -1, Psize * -1)
            End With

        Catch ex As Exception
            UpdateStatusLine("Dome picture error: '" & ex.Message & "'", Color.DarkRed)

        End Try

    End Sub

    Private Sub ButtonDomeStatus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeStatus.Click
        Dim Stats() As String
        Dim DomeMotor As String = "Motor: "
        Dim DomePos As String = "Az: "
        Dim DomeCmdPos As String = "Goto Az: "
        Dim DomeError As String = ",  Error: "
        Dim DomeMode As String = ""

        SendCommand("?")
        DomeStatus = DomeResponse
        Stats = Split(DomeStatus, ",")
        If UBound(Stats) = 4 Then
            If Stats(0) = "OK 0" Then DomeMotor = DomeMotor & "Off"
            If Stats(0) = "OK 1" Then DomeMotor = DomeMotor & "On"
            If Stats(1) = "-01" Then
                DomePos = DomePos & "Unknown"
            Else
                DomePos = DomePos & Stats(1)
            End If
            If Stats(2) <> "-01" Then
                DomeCmdPos = DomeCmdPos & Stats(2)
            End If
            If Stats(3) <> "0" Then
                Select Case Stats(3)
                    Case "1"
                        DomeError = DomeError & "RFID timeout"
                    Case "2"
                        DomeError = DomeError & "RFID not in table"
                    Case Else
                        DomeError = DomeError & "Unknown"
                End Select
            Else
                DomeError = ""
            End If
            If Stats(4) = "1" Then
                DomeMode = ", Emulator on"
                DomeControllerEmulatorModeOnOffToolStripMenuItem.Checked = True
            Else
                DomeControllerEmulatorModeOnOffToolStripMenuItem.Checked = False
            End If
            UpdateStatusLine(DomeStatus & "   " & DomeMotor & ",  " & DomePos & ",  " _
                & DomeCmdPos & DomeError & DomeMode, Color.Black)
        Else
            UpdateStatusLine(DomeStatus & "   Bad status received", Color.DarkRed)
        End If

    End Sub

    Private Sub ButtonDomeStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeStop.Click
        Select Case CtlType
            Case CtlNCO
                CheckBoxTrack.Checked = False
                SendCommand("STOP")
            Case CtlAGF
                CheckBoxTrack.Checked = False
                TimerMoveAGF.Enabled = False
                TimerDomeMoveAGF.Enabled = False
                TimeEnd = Microsoft.VisualBasic.DateAndTime.Timer
                SendCommand(":Q#")
                If RespGood = True Then
                    If DomeMovingAGF = True Then
                        TimeOfMove = TimeEnd - TimeStart
                        DegOfMove = MaskedTextBoxDegSec.Text / 100 * TimeOfMove
                        UpdateStatusLine("Move stopped after " & Format(DegOfMove, "0.00") & "° for " & _
                            Format(TimeOfMove, "0.00") & " seconds", Color.Black)
                        If DomeDirectionAGF = 1 Then
                            UpdateDomePicAGF(DomeStartPosAGF + DegOfMove)
                        Else
                            UpdateDomePicAGF(DomeStartPosAGF - DegOfMove)
                        End If
                    Else
                        UpdateStatusLine("Dome AGF stop", Color.Black)
                    End If
                End If
        End Select

    End Sub


    Private Sub TimerDomeMove_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerDomeMove.Tick
        If PollIndex > PollMax Then
            PollIndex = 0
        End If
        PictureBoxInd.Image = ImageList2.Images(PollIndex)
        PollIndex = PollIndex + 1
        ButtonDomeGet.PerformClick()

    End Sub

    Private Sub ButtonDomeSync_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeSync.Click
        ButtonDC.PerformClick()
        If DomeCalcGood = True Then
            TrackBarDome.Value = TrackBarScope.Value
            MoveDomePos()
        End If

    End Sub

    Private Sub ButtonMoveDomeToCalc_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonMoveDomeToCalc.Click
        Select Case CtlType
            Case CtlNCO
                If SocketIsOpen = True Then
                    TrackBarDome.Value = DomeCalcAz
                    MoveDomePos()
                Else
                    UpdateStatusLine("Not connected to Dome Controller", Color.DarkRed)
                End If

            Case CtlAGF
                If SerialPort2.IsOpen = True Or SocketIsOpen = True Then
                    TrackBarDome.Value = DomeCalcAz
                    MoveDomePos()
                Else
                    UpdateStatusLine("Not connected to AGF Dome Controller", Color.DarkRed)
                End If

        End Select

    End Sub

    Private Sub ButtonDomeGoto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDomeGoto.Click
        MoveDomePos()

    End Sub

    Private Sub MoveDomePos()
        Dim MoveDomeInterval As Integer = 0

        Select Case CtlType
            Case CtlNCO
                Dim MoveDomePos As Integer = TrackBarDome.Value
                SendCommand("GOAZ " & MoveDomePos)
                ' check response
                If Mid(DomeResponse, 1, 2) = "OK" Then
                    UpdateStatusLine("GOAZ " & MoveDomePos & " sent", Color.Black)
                End If
                If Mid(DomeResponse, 1, 4) = "Dome" Then
                    UpdateStatusLine("'" & DomeResponse & "' from GOAZ " & MoveDomePos, Color.Black)
                End If
                If Mid(DomeResponse, 1, 4) = "RFID" Then
                    UpdateStatusLine("'" & DomeResponse & "' from GOAZ ", Color.DarkRed)
                End If

            Case CtlAGF
                Dim DSec As Single = MaskedTextBoxDegSec.Text / 100
                Dim DomePOS As Integer = TrackBarDomePos.Value
                Dim MoveDeg As Integer = TrackBarDome.Value - DomePOS

                If DSec <= 0 Then
                    UpdateStatusLine("Move Deg. / sec. must be > 0.00", Color.DarkRed)
                    Exit Sub
                End If
                If MoveDeg = 0 Then
                    Exit Sub
                End If

                ' determine best direction
                If MoveDeg > 180 Then
                    MoveDeg = (360 - MoveDeg) * -1
                Else
                    If MoveDeg < -180 Then
                        MoveDeg = 360 + MoveDeg
                    End If
                End If

                MoveDomeTimeSec = MoveDeg / DSec
                DomeStartPosAGF = TrackBarDomePos.Value

                If ButtonAGFencoder.Checked = False Then
                    ' Uses time to move dome
                    If MoveDomeTimeSec > 0.0 Then
                        ' move cw
                        DomeDirectionAGF = 1
                        DomeMovingAGF = True
                        MoveDomeInterval = MoveDomeTimeSec * 1000
                        If TimerTrack.Enabled = True Then
                            TimerTrack.Enabled = False
                        End If
                        TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                        If MoveDomeInterval < 2000 Then
                            Dim Cmd As String = ":Te" & Format(MoveDomeInterval, "00000") & "#"
                            SendCommand(Cmd)
                            AGFtimedmove = True
                        Else
                            DomeAGFstop = ":Qe#"
                            SendCommand(":Me#")
                            AGFtimedmove = False
                        End If
                        If RespGood = True Then
                            UpdateStatusLine("Moving dome " & _
                                MoveDeg & "° CW for " & Format(MoveDomeTimeSec, "0.000") & " seconds to " & _
                                TrackBarDome.Value & "°", Color.Black)
                        End If
                    Else
                        ' move ccw
                        DomeDirectionAGF = -1
                        DomeMovingAGF = True
                        MoveDomeInterval = MoveDomeTimeSec * -1000
                        If TimerTrack.Enabled = True Then
                            TimerTrack.Enabled = False
                        End If
                        TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                        If MoveDomeInterval < 2000 Then
                            Dim Cmd As String = ":Tw" & Format(MoveDomeInterval, "00000") & "#"
                            SendCommand(Cmd)
                            AGFtimedmove = True
                        Else
                            DomeAGFstop = ":Qw#"
                            SendCommand(":Mw#")
                            AGFtimedmove = False
                        End If
                        If RespGood = True Then
                            UpdateStatusLine("Moving dome " & _
                                MoveDeg * -1 & "° CCW for " & Format(MoveDomeTimeSec * -1, "0.00") & " seconds to " & _
                                TrackBarDome.Value & "°", Color.Black)
                        End If
                    End If

                Else
                    ' Uses dome wheel pulses to move dome
                    Dim MoveDomeDeg As Integer = Math.Abs(MoveDeg)
                    If MoveDomeTimeSec > 0.0 Then
                        ' move cw
                        DomeDirectionAGF = 1
                        DomeMovingAGF = True
                        MoveDomeInterval = MoveDomeTimeSec * 1000
                        If TimerTrack.Enabled = True Then
                            TimerTrack.Enabled = False
                        End If
                        TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                        Dim Cmd As String = ":Re" & Format(MoveDomeDeg, "000") & "#"
                        SendCommand(Cmd)
                        AGFtimedmove = True
                        If RespGood = True Then
                            UpdateStatusLine("Moving dome " & _
                                MoveDeg & "° CW for " & Format(MoveDomeDeg, "000") & " degrees to " & _
                                TrackBarDome.Value & "°", Color.Black)
                        End If
                    Else
                        ' move ccw
                        DomeDirectionAGF = -1
                        DomeMovingAGF = True
                        MoveDomeInterval = MoveDomeTimeSec * -1000
                        If TimerTrack.Enabled = True Then
                            TimerTrack.Enabled = False
                        End If
                        TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                        Dim Cmd As String = ":Rw" & Format(MoveDomeDeg, "000") & "#"
                        SendCommand(Cmd)
                        AGFtimedmove = True
                        If RespGood = True Then
                            UpdateStatusLine("Moving dome " & _
                                MoveDeg & "° CCW for " & Format(MoveDomeDeg, "000") & " degrees to " & _
                                TrackBarDome.Value & "°", Color.Black)
                        End If
                    End If

                End If

                If RespGood = True Then
                    If MoveDomeTimeSec <> 0 Then
                        TimerMoveAGF.Interval = MoveDomeInterval
                        TimerMoveAGF.Enabled = True
                        TimerDomeMoveAGF.Enabled = True
                    End If
                Else
                    DSRswitchset = ConnectDSRport.Checked
                    TimerMoveAGF.Enabled = False
                    If CheckBoxTrack.Checked = True Then
                        CheckBoxTrack.Checked = False
                        UpdateStatusLine("Waiting for dome AGF connection", Color.DarkRed)
                        If Form1.AutoDomeTrackStartup.Checked = True Then
                            Talker.SpeakAsync("Waiting to reestablish AGF dome connection, dome auto tracking suspended")
                        End If
                        TimerAGFwait.Enabled = True
                    End If
                End If

        End Select

    End Sub

    Private Sub SendCommand(ByVal DomeCmd As String)
        If SerialPort2.IsOpen = True Or SocketIsOpen = True Then

            Select Case CtlType
                Case CtlNCO
                    Dim DomeRec(50) As Byte
                    Dim NumBytesRead As Integer

                    If TimerDomeMove.Enabled = True Then

                        Try
                            TimerDomeMove.Enabled = False
                            DomeRec = Encoding.ASCII.GetBytes(DomeCmd)
                            If NoDupStatusEntries.Checked = True And PrevSentNCO = DomeCmd Then
                            Else
                                LogDome("Sent > ", Color.DarkBlue, DomeCmd)
                            End If
                            PrevSentNCO = DomeCmd
                            networkStream.Write(DomeRec, 0, DomeCmd.Length)
                        Catch ex As Exception
                            LogDome("TCP > ", Color.DarkRed, ex.Message)
                            ButtonDomeConnect.PerformClick()
                            UpdateStatusLine("Dome controller write - ERROR, see log", Color.DarkRed)
                            MoveDome = False
                            If StopTrackingOnTimeout.Checked = True Then
                                CheckBoxTrack.Checked = False
                            End If
                            GoTo Cmd_DoneM
                        End Try

                        ' get response from dome controller
                        Try
                            DomeResponse = ""
                            Do
                                NumBytesRead = networkStream.Read(DomeRec, 0, DomeRec.Length)
                                DomeResponse = DomeResponse & Encoding.ASCII.GetString(DomeRec, 0, NumBytesRead)
                            Loop While networkStream.DataAvailable
                            If NoDupStatusEntries.Checked = True And PrevRecvNCO = DomeResponse Then
                            Else
                                LogDome("Resp < ", Color.DarkGreen, DomeResponse)
                            End If
                            PrevRecvNCO = DomeResponse
                        Catch ex As Exception
                            LogDome("TCP < ", Color.DarkRed, ex.Message)
                            ButtonDomeConnect.PerformClick()
                            UpdateStatusLine("Dome controller read - ERROR, see log", Color.DarkRed)
                            MoveDome = False
                            GoTo Cmd_DoneM
                        End Try
                        TimerDomeMove.Enabled = True

Cmd_DoneM:
                    End If

                Case CtlAGF
                    If AGFnetwork = False Then
                        SendReceiveAGF(DomeCmd)
                    Else
                        SendReceiveAGFnetwork(DomeCmd)
                    End If

            End Select

        End If

    End Sub

    Private Sub SendReceiveAGF(ByVal Command As String)
        Dim tickBegin As Long
        Dim tickEnd As Long
        Dim Tout As Integer = ComboBoxAGFtimeout.SelectedIndex + 1

        Try
            DomeResponse = ""
            SerialPort2.Write(Command)
            LogDome("Sent > ", Color.DarkBlue, Command)

            RespGood = True
            tickBegin = Int(Date.Now.Ticks / 10000000)
            Do Until Microsoft.VisualBasic.Right(DomeResponse, 1) = Chr(13)
                DomeResponse = DomeResponse & SerialPort2.ReadExisting()
                tickEnd = Int(Date.Now.Ticks / 10000000)
                If tickEnd - tickBegin > Tout Then
                    Dim Line As String
                    Line = "Timeout " & Tout & " sec. getting response from dome AGF"
                    UpdateStatusLine(Line, Color.DarkRed)
                    RespGood = False
                    If ConnectDSRport.Checked = True Then
                        Talker.Speak(Line)
                    End If
                    If StopTrackingOnTimeout.Checked = True Then
                        CheckBoxTrack.Checked = False
                    End If
                    Exit Do
                End If
                Application.DoEvents()
            Loop
        Catch ex As Exception
            If SerialPort2.IsOpen = False Then
                SetAGFportClosed()
            End If
            Dim Line As String = "Dome AGF SendReceive Error, " & ex.Message
            UpdateStatusLine(Line, Color.DarkRed)
            CheckBoxTrack.Checked = False
            If Form1.AutoDomeTrackStartup.Checked = True Then
                Talker.Speak(Line)
            End If
        End Try

        If RespGood = True Then
            If Microsoft.VisualBasic.Right(DomeResponse, 1) <> Chr(13) Then
                UpdateStatusLine("Invalid response from dome AGF '" & DomeResponse & "'", Color.DarkRed)
                RespGood = False
            Else
                DomeResponse = Mid(DomeResponse, 1, DomeResponse.Length - 1)
                LogDome("Resp < ", Color.DarkGreen, DomeResponse)
                RespGood = True
            End If
        End If

    End Sub

    Private Sub SendReceiveAGFnetwork(ByVal DomeCmd As String)
        Dim DomeRec(50) As Byte
        Dim NumBytesRead As Integer = 0

        RespGood = False
        Try
            DomeRec = Encoding.ASCII.GetBytes(DomeCmd)
            LogDome("Sent > ", Color.DarkBlue, DomeCmd)
            networkStream.Write(DomeRec, 0, DomeCmd.Length)
        Catch ex As Exception
            LogDome("TCP > ", Color.DarkRed, ex.Message)
            UpdateStatusLine("AGF Dome controller write - ERROR", Color.DarkRed)
            If StopTrackingOnTimeout.Checked = True Then
                CheckBoxTrack.Checked = False
            End If
            Exit Sub
        End Try

        ' get response from dome controller
        Try
            DomeResponse = ""
            Do
                NumBytesRead = networkStream.Read(DomeRec, 0, DomeRec.Length)
                DomeResponse = DomeResponse & Encoding.ASCII.GetString(DomeRec, 0, NumBytesRead)
            Loop Until Microsoft.VisualBasic.Right(DomeResponse, "1") = vbCr
            DomeResponse = DomeResponse.Replace(vbCr, "")
            LogDome("Resp < ", Color.DarkGreen, DomeResponse)
            RespGood = True
        Catch ex As Exception
            Dim Tsec As Integer = AGFtimeoutTCP / 1000
            'DomeResponse = " (AGF timeout " & Tsec & " seconds) check switch"
            LogDome("TCP < ", Color.DarkRed, ex.Message)
            UpdateStatusLine("AGF Dome controller read - ERROR", Color.DarkRed)
            If StopTrackingOnTimeout.Checked = True Then
                CheckBoxTrack.Checked = False
            End If
            Exit Sub
        End Try

    End Sub



    Private Sub TrackBarDome_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBarDome.ValueChanged
        If FormLoading = True Then Exit Sub
        LabelTmove.Text = TBmoveAz & TrackBarDome.Value

    End Sub

    Private Sub TrackBarScope_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBarScope.ValueChanged
        LabelTmount.Text = TBmountAz & TrackBarScope.Value
        ButtonDC.Enabled = True
        Form_ControlP.ButtonDomeTest.Enabled = True
        ButtonMoveDomeToCalc.Enabled = True

    End Sub

    Private Sub ButtonLocate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonLocate.Click
        If Active = True Then
            Active = False
            UDPWorker.CancelAsync()
            udpClient.Close()
        End If

        Try
            UpdateStatusLine("UDP Send=" & UDPsendPort & " Listen=" & UDPlistenPort, Color.Black)
            udpClient = New System.Net.Sockets.UdpClient()
            IPaddrUDP = IPAddress.Parse(UDPnetwork)
            udpClient.DontFragment = True
            udpClient.EnableBroadcast = True
            udpClient.MulticastLoopback = False
            udpClient.Connect(IPaddrUDP, UDPsendPort)

            UDPWorker = New System.ComponentModel.BackgroundWorker
            UDPWorker.WorkerReportsProgress = True
            UDPWorker.WorkerSupportsCancellation = True
            UDPWorker.RunWorkerAsync()

            Active = True
            TimerUdpTimeout.Enabled = True
        Catch ex As Exception
            UpdateStatusLine("Locate error '" & ex.Message & "'", Color.DarkRed)
        End Try

    End Sub

    Private Sub UDPWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles UDPWorker.DoWork
        Dim data As Byte()
        Dim RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, UDPlistenPort)

        udpClient.Send(sendBytes, sendBytes.Length)
        udpClient.Close()

        ' clear receive error message
        ReceiveEx = ""
        ' set udp socket to listen on
        Try
            udpClient = New System.Net.Sockets.UdpClient(UDPlistenPort)
            ' receive packets while Active is set true
            Do While Active
                Try
                    ' read data, blocking until data is received
                    data = udpClient.Receive(RemoteIpEndPoint)
                    ' convert byte array data to string
                    DataReceived = Encoding.ASCII.GetString(data)
                    ' address of remote ip
                    RemoteIP = RemoteIpEndPoint.Address.ToString
                    ' invoke ProcessChanged routine so data can be put on form
                    UDPWorker.ReportProgress(0, DataReceived)
                Catch ex As Exception
                    ' receive execption if active is false this is caused by program closing connection 
                    If Active = True Then
                        ' other error display message
                        ReceiveEx = ex.Message
                        UDPWorker.ReportProgress(0, "Error")
                    End If
                End Try
            Loop

        Catch ex As Exception
            ReceiveEx = ex.Message
            UDPWorker.ReportProgress(0, "Error")
        End Try

    End Sub

    Private Sub UDPWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles UDPWorker.ProgressChanged
        If ReceiveEx = "" Then
            LabelRemoteIP.Text = RemoteIP
            UpdateStatusLine(DataReceived & "  IP " & RemoteIP, Color.Black)
            ButtonDomeConnect.Enabled = True
        Else
            UpdateStatusLine(ReceiveEx, Color.DarkRed)
        End If
        Active = False
        UDPWorker.CancelAsync()
        udpClient.Close()

    End Sub

    Private Sub TimerUdpTimeout_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerUdpTimeout.Tick
        If Active = True Then
            Active = False
            UDPWorker.CancelAsync()
            udpClient.Close()
            UpdateStatusLine("Could not locate Dome Controller, Timeout", Color.DarkRed)
        End If
        TimerUdpTimeout.Enabled = False

    End Sub


    Private Sub ButtonMoveCCW_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ButtonMoveCCW.MouseDown
        Dim GoodResp As String = ""

        Select Case CtlType
            Case CtlNCO
                SendCommand("MOVE 1")
                GoodResp = "OK"
            Case CtlAGF
                DomeDirectionAGF = -1
                DomeStartPosAGF = TrackBarDomePos.Value
                TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                SendCommand(":Mw#")
                GoodResp = "Guide west"
                TimerDomeMoveAGF.Enabled = True
        End Select
        ' check for good response
        If Mid(DomeResponse, 1, GoodResp.Length) = GoodResp Then
            UpdateStatusLine("Moving dome CCW", Color.Black)
            MoveDome = True
            MoveError = False
        Else
            MoveError = True
            TimerDomeMoveAGF.Enabled = False
        End If

    End Sub

    Private Sub ButtonMoveCCW_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ButtonMoveCCW.MouseUp
        If MoveError = False Then
            MoveDome = False
            Select Case CtlType
                Case CtlNCO
                    SendCommand("MOVE 0")
                    ButtonDomeGet.PerformClick()
                    UpdateStatusLine("Move stopped", Color.Black)
                Case CtlAGF
                    TimeEnd = Microsoft.VisualBasic.DateAndTime.Timer
                    SendCommand(":Qw#")
                    TimerDomeMoveAGF.Enabled = False
                    TimeOfMove = TimeEnd - TimeStart
                    DegOfMove = MaskedTextBoxDegSec.Text / 100 * TimeOfMove
                    If RespGood = True Then
                        UpdateStatusLine("Move stopped " & Format(DegOfMove, "0.00") & "° CCW for " & _
                            Format(TimeOfMove, "0.000") & " seconds", Color.Black)
                        UpdateDomePicAGF(DomeStartPosAGF - DegOfMove)
                    End If
            End Select
        End If

    End Sub

    Private Sub ButtonMoveCW_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ButtonMoveCW.MouseDown
        Dim GoodResp As String = ""

        Select Case CtlType
            Case CtlNCO
                SendCommand("MOVE 2")
                GoodResp = "OK"
            Case CtlAGF
                DomeDirectionAGF = 1
                DomeStartPosAGF = TrackBarDomePos.Value
                TimeStart = Microsoft.VisualBasic.DateAndTime.Timer
                SendCommand(":Me#")
                GoodResp = "Guide east"
                TimerDomeMoveAGF.Enabled = True
        End Select
        ' check for good response
        If Mid(DomeResponse, 1, GoodResp.Length) = GoodResp Then
            UpdateStatusLine("Moving dome CW", Color.Black)
            MoveDome = True
            MoveError = False
        Else
            MoveError = True
            TimerDomeMoveAGF.Enabled = False
        End If

    End Sub

    Private Sub ButtonMoveCW_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ButtonMoveCW.MouseUp
        If MoveError = False Then
            MoveDome = False
            Select Case CtlType
                Case CtlNCO
                    SendCommand("MOVE 0")
                    ButtonDomeGet.PerformClick()
                    UpdateStatusLine("Move stopped", Color.Black)
                Case CtlAGF
                    TimeEnd = Microsoft.VisualBasic.DateAndTime.Timer
                    SendCommand(":Qe#")
                    TimerDomeMoveAGF.Enabled = False
                    TimeOfMove = TimeEnd - TimeStart
                    DegOfMove = MaskedTextBoxDegSec.Text / 100 * TimeOfMove
                    If RespGood = True Then
                        UpdateStatusLine("Move stopped " & Format(DegOfMove, "0.00") & "° CW for " & _
                            Format(TimeOfMove, "0.000") & " seconds", Color.Black)
                        UpdateDomePicAGF(DomeStartPosAGF + DegOfMove)
                    End If
            End Select
        End If

    End Sub

    Private Sub UpdateDomePicAGF(ByVal NewDomePos As Single)
        Try
            If NewDomePos >= 360 Then
                NewDomePos = NewDomePos - 360
            End If
            If NewDomePos < 0 Then
                NewDomePos = 360 + NewDomePos
            End If
            TrackBarDomePos.Value = Int(NewDomePos)
            LabelTdome.Text = TBdomeAz & TrackBarDomePos.Value
            DomeRotate = TrackBarDomePos.Value
            PictureBoxDome.Refresh()
        Catch ex As Exception
            UpdateStatusLine("Update dome position error at " & NewDomePos & "°", Color.DarkRed)
        End Try

    End Sub

    Private Sub CheckBoxTrack_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles CheckBoxTrack.CheckedChanged
        Dim Line As String = ""
        Dim StatusDone As Boolean = False

        If CheckBoxTrack.Checked = True Then
            ButtonDomeGoto.Enabled = False
            ButtonMoveCCW.Enabled = False
            ButtonMoveCW.Enabled = False
            ButtonDomeSync.Enabled = False
            ButtonGetAz.Enabled = False
            Line = "Dome tracking starting"
            UpdateStatusLine(Line, Color.Black)
            GetMountAZ()
            If GetScopePos.RespGood = True Then
                If DomeCalcAz = -1 Then
                    CalcDomePos()
                End If
                MonitorCmdSave = Form1.MonitorCmd
                Line = "Dome tracking enabled"
                TrackDotCount = 0
                TimerTrack.Enabled = True
                Form1.TextBoxDome.ForeColor = Color.Blue
                Form1.CheckBoxDT.Checked = True
            Else
                CheckBoxTrack.Checked = False
                Line = "Dome tracking aborted, get Alt/Az from mount error"
                UpdateStatusLine(Line, Color.DarkRed)
                StatusDone = True
            End If

        Else
            TimerTrack.Enabled = False
            ButtonDomeGoto.Enabled = True
            ButtonMoveCCW.Enabled = True
            ButtonMoveCW.Enabled = True
            ButtonDomeSync.Enabled = True
            ButtonGetAz.Enabled = True
            'GroupBox2.Enabled = True
            Form1.MonitorCmd = MonitorCmdSave
            Form1.TextBoxDome.ForeColor = Color.CornflowerBlue
            Form1.CheckBoxDT.Checked = False
            If RespGood = True Then
                If GetScopePos.RespGood = True Then
                    Line = "Dome tracking disabled"
                    If ConnectDSRport.Checked = True And DSRswitch = False Then
                        Talker.SpeakAsync(Line)
                    End If
                Else
                    Line = "Dome tracking disabled, error getting position from mount"
                    If ConnectDSRport.Checked = True Then
                        Talker.SpeakAsync(Line)
                    End If
                End If
            Else
                Line = "Dome tracking disabled, dome controller error"
                If ConnectDSRport.Checked = True Then
                    Talker.SpeakAsync(Line)
                End If
            End If
        End If
        If StatusDone = False Then
            UpdateStatusLine(Line, Color.Black)
        End If

        'If ConnectDSRport.Checked = True And DSRswitch = False And ComBreakIssued = False Then
        '    'ConnectDSRport.Checked = False
        '    Dim Line As String = "DSR switch disabled, by user interface"
        '    Talker.SpeakAsync(Line)
        '    UpdateStatusLine(Line, Color.Black)
        'End If

    End Sub

    Private Sub GetMountAZ()
        Dim GoodValue As Boolean = True

        If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
            GetScopeAzEl()
            If GetScopePos.RespGood = True Then
                AP_AL = Mid(Form1.AP_AL, 1, 3)
                AP_AZ = Form1.AP_AZ
                If AP_AZ = "" Then
                    UpdateStatusLine("No response from mount for Get Azimuth", Color.DarkRed)
                Else
                    Try
                        GoodValue = True
                        ScopeSaveAz = ScopeCurAz
                        ScopeSavePos = ScopeCurPos
                        Dim StartDeg As Integer
                        Dim StartMin As Integer
                        Dim StartSec As Integer
                        StartDeg = InStr(AP_AZ, "+")
                        StartMin = InStr(AP_AZ, "*")
                        StartSec = StartMin + 3
                        AZdeg = Mid(AP_AZ, StartDeg + 1, StartMin - StartDeg - 1)
                        AZmin = Mid(AP_AZ, StartMin + 1, 2)
                        AZsec = Mid(AP_AZ, StartSec + 1, 2)
                        ScopeCurPos = AZdeg
                        GetMeridianDist()

                        If GoodValue = True Then
                            TrackBarScope.Value = AZdeg
                            ScopeCurAz = AZdeg
                            LabelTmount.Text = TBmountAz & TrackBarScope.Value
                            LabelMaz.Text = Format(ScopeCurAz, "000")
                            Form1.Update_Scope_Pos()
                        Else
                            UpdateStatusLine("Invalid azimuth from mount = " & AP_AZ, Color.DarkRed)
                        End If
                    Catch ex As Exception
                        UpdateStatusLine(ex.Message & " Exception in Dome GetMountAZ = " & AP_AZ, Color.DarkRed)
                    End Try
                End If
            End If

        End If


    End Sub


    Private Sub CommandsSentResponseToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CommandsSentResponseToolStripMenuItem1.Click
        Form_DOME_SENT_RESP_LOG.Show()
        Form_DOME_SENT_RESP_LOG.Focus()

    End Sub

    Private Sub LastStatusReceivedToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LastStatusReceivedToolStripMenuItem1.Click
        UpdateStatusLine("Last status = " & DomeStatus, Color.Black)

    End Sub

    Private Sub DomeControllerVersionToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DomeControllerVersionToolStripMenuItem.Click
        Select Case CtlType
            Case CtlNCO
                If SocketIsOpen = True Then
                    SendCommand("V")
                    UpdateStatusLine(DomeResponse, Color.Black)
                Else
                    UpdateStatusLine("Not connected", Color.DarkRed)
                End If
            Case CtlAGF
                SendCommand(":V#")
                If DomeResponse <> "" Then
                    UpdateStatusLine(DomeResponse, Color.Black)
                End If
        End Select

    End Sub

    Private Sub DomeControllerHelpToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DomeControllerHelpToolStripMenuItem.Click
        Select Case CtlType
            Case CtlNCO
                If SocketIsOpen = True Then
                    SendHelpCommand()
                    Form_DomeHelp.TextBox1.Text = HelpResponse
                    Form_DomeHelp.TextBox1.Select(Form_DomeHelp.TextBox1.Text.Length, 0)
                    Form_DomeHelp.Show()
                Else
                    UpdateStatusLine("Not connected", Color.DarkRed)
                End If
            Case CtlAGF
                StatusLabel.Text = "See PDF document under main program Menu"
        End Select

    End Sub

    Private Sub SendHelpCommand()
        Dim DomeRec(50) As Byte
        Dim NumBytesRead As Integer
        Dim DomeHelpCmd As String = "HELP"
        Dim X As String

        TimerDomeMove.Enabled = False
        Me.Cursor = Cursors.WaitCursor
        Application.DoEvents()

        ' send command to dome controller
        DomeSent = DomeHelpCmd
        UpdateStatusLine("Sending HELP command", Color.Black)
        Application.DoEvents()
        Try
            DomeRec = Encoding.ASCII.GetBytes(DomeHelpCmd)
            networkStream.Write(DomeRec, 0, DomeHelpCmd.Length)
        Catch ex As Exception
            LogDome("TCP (help) > ", Color.DarkRed, ex.Message)
            ButtonDomeConnect.PerformClick()
            UpdateStatusLine(StatusLabel.Text & " - ERROR, see log", Color.DarkRed)
            GoTo Cmdhelp_Done
        End Try

        ' get response from dome controller
        UpdateStatusLine("Receiving HELP response", Color.Black)
        Application.DoEvents()
        Try
            HelpResponse = ""
            Do
                Do
                    NumBytesRead = networkStream.Read(DomeRec, 0, DomeRec.Length)
                    HelpResponse = HelpResponse & Encoding.ASCII.GetString(DomeRec, 0, NumBytesRead)
                Loop While networkStream.DataAvailable
                X = Microsoft.VisualBasic.Right(HelpResponse, 1)
            Loop Until X = Chr(3)
            HelpResponse = Mid(HelpResponse, 1, HelpResponse.Length - 3)
        Catch ex As Exception
            LogDome("TCP (help) < ", Color.DarkRed, ex.Message)
            ButtonDomeConnect.PerformClick()
            UpdateStatusLine(StatusLabel.Text & " - ERROR, see log", Color.DarkRed)
            GoTo CmdHelp_Done
        End Try

        UpdateStatusLine("Dome help", Color.Black)
        TimerMoveAGF.Enabled = True
        TimerDomeMove.Enabled = True

CmdHelp_Done:
        Me.Cursor = Cursors.Default

    End Sub

    Private Sub StatusLineFullTextToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StatusLineFullTextToolStripMenuItem.Click
        Form_DomeHelp.TextBox1.Text = StatusLabel.Text
        Form_DomeHelp.TextBox1.Select(Form_DomeHelp.TextBox1.Text.Length, 0)
        Form_DomeHelp.Show()

    End Sub

    Private Sub StatusLabel1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles StatusLabel.Click
        StatusLineFullTextToolStripMenuItem.PerformClick()

    End Sub

    Private Sub DomeControllerWebPageToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DomeControllerWebPageToolStripMenuItem1.Click
        Try
            Select Case CtlType
                Case CtlNCO
                    Url0 = "http://" & RemoteIP
                    WebPageDisplay()
                Case CtlAGF
                    Url0 = "http://" & AGFipAddress
                    WebPageDisplay()
            End Select

        Catch ex As Exception
            UpdateStatusLine("Dome controller web page connect error: " & ex.Message, Color.DarkRed)

        End Try

    End Sub

    Private Sub CalibrateDomeToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CalibrateDomeToolStripMenuItem1.Click
        If SocketIsOpen = True Then
            Url0 = "http://" & RemoteIP & "/settings.html"
            WebPageDisplay()
        Else
            UpdateStatusLine("Not connected", Color.DarkRed)
        End If

    End Sub

    Private Sub WebPageDisplay()
        If InternalWebToolStripMenuItem.Checked = True Then
            Form_Web.WebBrowser1.Navigate(Url0)
            Form_Web.Show()
            UpdateStatusLine("Show web page " & Url0, Color.Black)
        Else
            ' display web page in default browser
            Dim psInfo As New  _
                   System.Diagnostics.ProcessStartInfo(Url0)
            psInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
            Dim myProcess As Process = _
               System.Diagnostics.Process.Start(psInfo)
        End If

    End Sub

    Private Sub SendDomeINITCommandToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SendDomeINITCommandToolStripMenuItem.Click
        UpdateStatusLine("Sending INIT, waiting 6 seconds", Color.Black)
        Application.DoEvents()
        SendCommand("INIT")
        Thread.Sleep(6000)
        If Mid(DomeResponse, 1, 2) = "OK" Then
            UpdateStatusLine("INIT sent " & DomeResponse, Color.Black)
        Else
            UpdateStatusLine("INIT failed, " & DomeResponse, Color.DarkRed)
        End If

    End Sub

    Private Sub UseLocalhostToLocateDomeControllerEmulatorToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UseLocalhostToLocateDomeControllerEmulatorToolStripMenuItem.Click
        If UseLocalhostToLocateDomeControllerEmulatorToolStripMenuItem.Checked = True Then
            SetUDPnetwork(0)
        Else
            SetUDPnetwork(1)
        End If

    End Sub

    Private Sub UseRemoteNetworkToLocateDomeControllerEmulatorToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UseRemoteNetworkToLocateDomeControllerEmulatorToolStripMenuItem.Click
        If UseRemoteNetworkToLocateDomeControllerEmulatorToolStripMenuItem.Checked = True Then
            SetUDPnetwork(0)
        Else
            SetUDPnetwork(4)
        End If

    End Sub

    Private Sub UseNetworkMaskBelowToLocateDomeControllerToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UseNetworkMaskBelowToLocateDomeControllerToolStripMenuItem.Click
        Try
            If UseNetworkMaskBelowToLocateDomeControllerToolStripMenuItem.Checked = True Then
                SetUDPnetwork(0)
            Else
                SetIPaddr = IPAddress.Parse(ToolStripTextBoxMask.Text)
                SetUDPnetwork(3)
            End If
        Catch
            UpdateStatusLine("Set network address not valid " & ToolStripTextBoxMask.Text, Color.DarkRed)
        End Try

    End Sub

    Private Sub UseIPAddressBelowForDomeControllerToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UseIPAddressBelowForDomeControllerToolStripMenuItem.Click
        Dim DomeIP As String
        Dim ValidateIP As IPAddress

        DomeIP = ToolStripTextBoxIP.Text
        Try
            ValidateIP = IPAddress.Parse(DomeIP)
            RemoteIP = DomeIP
            LabelRemoteIP.Text = DomeIP
            ButtonDomeConnect.Enabled = True
        Catch
            UpdateStatusLine("Set Dome Controller IP address not valid " & DomeIP, Color.DarkRed)
            ButtonDomeConnect.Enabled = False
        End Try

    End Sub

    Private Sub DomeControllerEmulatorModeOnOffToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DomeControllerEmulatorModeOnOffToolStripMenuItem.Click
        If SocketIsOpen = True Then
            If DomeControllerEmulatorModeOnOffToolStripMenuItem.Checked = True Then
                SendCommand("MODE 0")
                DomeControllerEmulatorModeOnOffToolStripMenuItem.Checked = False
            Else
                SendCommand("MODE 1")
                DomeControllerEmulatorModeOnOffToolStripMenuItem.Checked = True
            End If
        Else
            UpdateStatusLine("Not connected", Color.DarkRed)
        End If

    End Sub

    Private Sub InternalWebToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles InternalWebToolStripMenuItem.Click
        If InternalWebToolStripMenuItem.Checked = True Then
            InternalWebToolStripMenuItem.Checked = False
        Else
            InternalWebToolStripMenuItem.Checked = True
        End If

    End Sub

    Private Sub ButtonDC_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDC.Click
        StatusLabel.Text = ""
        CalcDomePos()

    End Sub

    Private Sub CalcDomePos()
        ' conversions
        'Const DEG_RAD As Double = 0.0174532925
        Const RAD_DEG As Double = 57.2957795
        Const HRS_RAD As Double = 0.2617993881
        'Const RAD_HRS As Double = 3.81971863

        ' scope geometry wrt dome
        Dim g_dRadius As Double = 0.0                ' dome radius in m
        Dim g_iPosEW As Double = 0.0                 ' scope offset in mm
        Dim g_iPosNS As Double = 0.0                 ' scope offset in mm
        Dim g_iPosUD As Double = 0.0                 ' scope offset in mm
        Dim g_iGEMOffset As Integer = 0.0            ' GEM axis offset
        Dim g_iGEMOffsetEW As Integer = 0.0          ' GEM axis offset east or west
        Dim g_dLatitude As Double = 0.0              ' latitude in dec. deg.
        'Dim g_iSlop As Integer                       ' precision for dome moves

        Dim HA As Double
        Dim pierWest As Boolean = False
        Dim SiderealTime As Double
        Dim ScopeRA As Double
        Dim dc As New DomeControl

        StatusLabel.Text = ""
        g_dRadius = TextBoxDomeRadius.Text / 100
        g_iPosUD = TextBoxUpDown.Text
        g_iGEMOffset = TextBoxOTA.Text
        g_iGEMOffsetEW = TextBoxOTAEW.Text
        g_iPosNS = TextBoxMntNS.Text
        'g_iPosEW = TextBoxOTAEW.Text


        ' get ra from telescope
        Try
            If CheckBoxTrack.Checked = False Then
                GetMountAZ()
            End If
            GetScopeRaDec()
            If Form1.TelescopeSide = "West" Then
                pierWest = True
            Else
                ' adjust scope East/West offset for side of pier (added v19.13-0)
                g_iGEMOffsetEW = g_iGEMOffsetEW * -1
            End If
            SRA = Form1.AP_RA
            ScopeRA = Mid(SRA, 1, 2) + (Mid(SRA, 4, 2) / 60) + (Mid(SRA, 7, 4) / 3600)

            SST = Form1.TelescopeST
            If SST.Length >= 10 Then
                SiderealTime = Mid(SST, 1, 2) + (Mid(SST, 4, 2) / 60) + (Mid(SST, 7, 4) / 3600)
            Else
                UpdateStatusLine("Cannot get sidereal time from scope " & SST, Color.DarkRed)
                Exit Sub
            End If

            If Lat.Length = 0 Then
                Form1.AP_Command("Latitude")
                Lat = Form1.TelescopeLat
            End If
            If Lat.Length >= 9 Then
                g_dLatitude = Mid(Lat, 2, 2) + (Mid(Lat, 5, 2) / 60) + (Mid(Lat, 8, 2) / 3600)
            Else
                UpdateStatusLine("Cannot get latitude from scope " & Form1.TelescopeLat, Color.DarkRed)
                Exit Sub
            End If

            ' calculate hour angle from the supplied values in Radians
            HA = HAScale(SiderealTime - ScopeRA) * HRS_RAD

            ' convert scope alt az for DomeControl format
            Dim scopeAlt As Double, scopeAzm As Double
            If Form1.AP_AZ = "" Then
                GetMountAZ()
            End If
            SAL = Form1.AP_AL
            SAZ = Form1.AP_AZ
            scopeAzm = (AZdeg + (AZmin / 60) + (AZsec / 3600))
            'If SAZ.Length = 10 Then
            '    scopeAzm = Mid(SAZ, 2, 3) + (Mid(SAZ, 6, 2) / 60) + (Mid(SAZ, 9, 2) / 3600)
            'Else
            '    scopeAzm = Mid(SAZ, 2, 2) + (Mid(SAZ, 5, 2) / 60) + (Mid(SAZ, 8, 2) / 3600)
            'End If
            scopeAlt = Mid(SAL, 1, 3) + (Mid(SAL, 5, 2) / 60) + (Mid(SAL, 8, 2) / 3600)

            If DebugLog = True Then
                LogError_Debug()
            End If

            ' dome conversion using DomeControl
            Try
                If g_dRadius > 0.0 Then
                    dc.InitDome(g_dRadius * 1000, _
                                CDbl(g_iGEMOffset), _
                                CDbl(g_iGEMOffsetEW), _
                                CDbl(g_iPosNS), _
                                CDbl(g_iPosEW), _
                                CDbl(g_iPosUD), _
                                CDbl(g_dLatitude), _
                                True)

                    DomeAz = dc.DomeAzimuth(scopeAzm, scopeAlt, HA * RAD_DEG, pierWest)

                    If DebugLog = True Then
                        LogDebug("DomeCalc Init inputs --")
                        LogDebug("dome radius : " & Format(g_dRadius * 1000, "0.00"))
                        LogDebug("ota offset RA center : " & Format(g_iGEMOffset, "0.00"))
                        LogDebug("ota offset E- W+ : " & Format(g_iGEMOffsetEW, "0.00"))
                        LogDebug("mount offset N+ S- : " & Format(g_iPosNS, "0.00"))
                        LogDebug("mount offset E- W+ : " & Format(g_iPosEW, "0.00"))
                        LogDebug("mount height : " & Format(g_iPosUD, "0.00"))
                        LogDebug("latitude : " & Format(g_dLatitude, "0.00"))
                        LogDebug("mount is GEM : True")
                        LogDebug("DomeCalc Azimuth inputs --")
                        LogDebug("scopeAzm : " & Format(scopeAzm, "0.00"))
                        LogDebug("scopeAlt : " & Format(scopeAlt, "0.00"))
                        LogDebug("HA * RAD_DEG : " & Format(HA * RAD_DEG, "0.00"))
                        LogDebug("pierWest : " & pierWest)
                        LogDebug("DomeCalcPos. : " & Format(DomeAz, "000"))
                        LogDebug("--")
                    End If
                Else
                    DomeAz = TrackBarScope.Value
                End If

                DomeCalcAz = DomeAz + (NumericUpDownMD.Value * 15)
                If DomeCalcAz >= 360 Then
                    DomeCalcAz = DomeCalcAz - 360
                End If
                If DomeCalcAz < 0 Then
                    DomeCalcAz = DomeCalcAz + 360
                End If
                LabelCalc.Text = Format(DomeCalcAz, "000")
                DomeCalcGood = True
                DupLogCheck = True
                UpdateStatusLine("Scope Alt/Az " & AP_AL & "°/" & ScopeCurPos & "°, Dome Calc Az " & DomeCalcAz & "° ", Color.Black)
                DupLogCheck = False
                'Form1.StatusLabel.Text = Format(DomeCalcAz, "000")

            Catch ex As Exception
                DomeCalcGood = False

            End Try

        Catch ex As Exception
            DomeCalcGood = False
            UpdateStatusLine("Error in Dome Calc position", Color.DarkRed)
            LogError_Debug()
            If ConnectDSRport.Checked = True Then
                Talker.SpeakAsync("Error in Dome Calc position")
            End If
            If StopTrackingOnTimeout.Checked = True Then
                CheckBoxTrack.Checked = False
            End If
        End Try

    End Sub

    Private Sub LogError_Debug()
        LogDebug("RA : " & SRA)
        LogDebug("DEC : " & Form1.AP_DEC)
        LogDebug("ALt : " & SAL)
        LogDebug("AZ : " & SAZ)
        LogDebug("Lat : " & Lat)
        LogDebug("Sidreal : " & SST)
    End Sub


    ' range the azimuth parameter
    Public Function HAScale(ByVal HA As Double) As Double

        While HA < -12
            HA = HA + 24
        End While
        While HA >= 12
            HA = HA - 24
        End While

        HAScale = HA

    End Function

    Private Sub TimerTrack_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerTrack.Tick
        Dim DegToChange As Integer = NumericUpDownSyncDeg.Value

        If DomeCalcAz >= 0 Then
            GetMountAZ()
            If GetScopePos.RespGood = False Then
                Exit Sub
            End If
            If ScopeCurPos = ScopeSavePos Then
                If ScopeCurAz = ScopeSaveAz Then
                    'If ScopeCurAz <> DomeCurAz Then
                    If DebugLog = True Then
                        LogDebug("Do CalcDomePos")
                        LogDebug("ScopeCurAz = " & ScopeCurAz)
                        LogDebug("DomeCurAz = " & DomeCurAz)
                    End If
                    CalcDomePos()
                    TrackDotCount = TrackDotCount + 1
                    If TrackDotCount > 3 Then
                        TrackDotCount = 1
                    End If
                    Select Case TrackDotCount
                        Case 1
                            StatusLabel.Text = StatusLabel.Text & "  " & Form1.AP_MeridianDist & " ●"
                        Case 2
                            StatusLabel.Text = StatusLabel.Text & "  " & Form1.AP_MeridianDist & " ●●"
                        Case 3
                            StatusLabel.Text = StatusLabel.Text & "  " & Form1.AP_MeridianDist & " ●●●"
                    End Select
                    'Form1.TextBoxDome.Text = StatusLabel.Text
                    If DomeCalcAz <> TrackBarDome.Value Then
                        If DegToChange > 1 Then
                            Dim DomeChange As Integer = Math.Abs(DomeCalcAz - TrackBarDome.Value)
                            If DomeChange >= DegToChange Then
                                TrackBarDome.Value = DomeCalcAz
                                MoveDomePos()
                                If DebugLog = True Then
                                    LogDebug("DomeChange : " & DomeChange)
                                    LogDebug("DegToChange : " & DegToChange)
                                    LogDebug("DomeCalcAz : " & DomeCalcAz)
                                End If
                            End If
                        Else
                            TrackBarDome.Value = DomeCalcAz
                            MoveDomePos()
                        End If
                        'End If
                    End If
                End If
            Else
                UpdateStatusLine("Scope is moving from Az " & ScopeSavePos & "° to " & ScopeCurPos & "°", Color.Black)
            End If
        End If

    End Sub

    Private Sub ComboBoxDomes_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBoxDomes.SelectedIndexChanged
        Dim Domes() As String
        Dim I As Integer = 1

        Form1.DomeCurrent = ComboBoxDomes.SelectedIndex

        Domes = Split(ComboBoxDomes.SelectedItem, ",")
        While I <= UBound(Domes)
            Select Case I
                Case 1
                    TextBoxDomeRadius.Text = Domes(1)
                Case 2
                    TextBoxOTA.Text = Domes(2)
                Case 3
                    TextBoxOTAEW.Text = Domes(3)
                Case 4
                    TextBoxUpDown.Text = Domes(4)
                Case 5
                    MaskedTextBoxDegSec.Text = Domes(5)
                Case 6
                    TextBoxMntNS.Text = Domes(6)
            End Select
            I = I + 1
        End While

        Dim Line As String = ComboBoxDomes.SelectedItem
        LogDome("Config = ", Color.Black, Line)

        Select Case CtlType
            Case CtlAGF
                If MaskedTextBoxDegSec.Text = 0 Then
                    UpdateStatusLine("AGF Dome movement rate is zero", Color.DarkRed)
                Else
                    UpdateStatusLine("AGF Dome parameters set", Color.Black)
                End If

            Case CtlNCO
                UpdateStatusLine("NCO Dome parameters set", Color.Black)

        End Select

    End Sub

    Private Sub NumericUpDownTrack_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NumericUpDownTrack.ValueChanged
        TimerTrack.Interval = NumericUpDownTrack.Value * 1000

    End Sub

    Private Sub StatusLabel_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles StatusLabel.MouseUp
        If (e.Button = Windows.Forms.MouseButtons.Right) Then
            StatusLabel.Text = ""
        End If

    End Sub

    Private Sub TabControl1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TabControl1.SelectedIndexChanged
        If SerialPort2.IsOpen = False And SocketIsOpen = False Then
            SetMenuControl()
        End If

    End Sub

    Public Sub SetMenuControl()
        CtlType = TabControl1.SelectedIndex
        If CtlType = CtlAGF Then
            ControlToolStripMenuItem1.Visible = False
            AGFcontrol.Visible = True
            Me.Icon = My.Resources.Dome_AGF
            Form1.DomeToolStripMenuItem.Image = My.Resources.Dome_AGF_image
        Else
            ControlToolStripMenuItem1.Visible = True
            AGFcontrol.Visible = False
            Me.Icon = My.Resources.Dome_NCO
            Form1.DomeToolStripMenuItem.Image = My.Resources.Dome_NCO_image
        End If

    End Sub

    REM AGF Control Tab routines

    Private Sub ButtonAGFconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAGFconnect.Click
        Dim ComPort As String

        ComPort = Trim(Microsoft.VisualBasic.Left(ComboBoxAGF.Items(ComboBoxAGF.SelectedIndex), 6))

        If ComPort = "Networ" Then
            AGFnetwork = True
            AGFnetworkConnect()
            Exit Sub
        Else
            AGFnetwork = False
        End If

        Try
            If SerialPort2.IsOpen = False Then
                SerialPort2.PortName = ComPort
                UpdateStatusLine("Opening " & SerialPort2.PortName, Color.Black)
                Application.DoEvents()
                ActiveCtl = CtlAGF
                SerialPort2.Open()
                SendCommand(":I#")
                If DomeResponse = "" Then
                    UpdateStatusLine("No response from AGF dome controller", Color.DarkRed)
                    SerialPort2.Close()
                Else
                    If Mid(DomeResponse, 1, 3) = "(A)" Then
                        AGFarduino = True
                        GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = True
                    Else
                        AGFarduino = False
                        GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = False
                    End If
                    TimerAGFdiag.Enabled = False
                    AGFdomeEmulatorMode.Checked = False
                    StartComDiag.Checked = False
                    DebugAGF.Checked = False
                    ButtonAGFconnect.Text = "Disconnect"
                    ButtonDomeConnect.Enabled = False
                    ButtonLocate.Enabled = False
                    ButtonDomeGoto.Enabled = True
                    ButtonDomeStop.Enabled = True
                    ButtonMoveCCW.Enabled = True
                    ButtonMoveCW.Enabled = True
                    ButtonDomeSync.Enabled = ButtonGetAz.Enabled
                    CheckBoxTrack.Enabled = ButtonGetAz.Enabled
                    Form1.CheckBoxDT.Enabled = CheckBoxTrack.Enabled
                    ButtonLocate.Enabled = False
                    Form_ControlP.ButtonDomeTest.Enabled = True
                    InitializeAGFDomeController.Enabled = True
                    AGFdomeEmulatorMode.Enabled = True
                    StartComDiag.Enabled = True
                    GetAGFExtendedStatus.Enabled = True
                    GetDomeWheelBias.Enabled = True
                    SetDomeWheelBias.Enabled = True
                    DebugAGF.Enabled = True
                    If DebugAGF.Checked = True Then
                        SetDebugAGF(True)
                    End If
                    PictureBoxInd.Visible = True
                    If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
                        ButtonDC.Enabled = True
                        ButtonMoveDomeToCalc.Enabled = True
                        If ConnectDSRport.Checked = True Then
                            GetDSRcheckState()
                        End If
                    End If
                    UpdateStatusLine("Connected " & SerialPort2.PortName & "  " & DomeResponse, Color.Black)
                    DomeConnected = True
                End If
            Else
                CheckBoxTrack.Checked = False
                TimerDomeMoveAGF.Enabled = False
                TimerAGFdiag.Enabled = False
                AGFdomeEmulatorMode.Checked = False
                AGFdomeEmulatorMode.Enabled = False
                Form_ControlP.ButtonDomeTest.Enabled = False
                InitializeAGFDomeController.Enabled = False
                AGFdomeEmulatorMode.Enabled = False
                StartComDiag.Enabled = False
                StartComDiag.Checked = False
                DebugAGF.Enabled = False
                SendCommand(":I#")
                AGFarduino = False
                GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = False
                SerialPort2.Close()
                SetAGFportClosed()
                UpdateStatusLine("Disconnected " & SerialPort2.PortName, Color.Black)
                DomeConnected = False
            End If

        Catch ex As Exception
            UpdateStatusLine("Serial port open/close error: " & ex.Message, Color.DarkRed)
            If SerialPort2.IsOpen = False Then
                SetAGFportClosed()
            End If
        End Try

    End Sub

    Private Sub SetAGFportClosed()
        ButtonAGFconnect.Text = "Connect"
        ButtonDomeConnect.Enabled = True
        ButtonLocate.Enabled = True
        ButtonDomeGoto.Enabled = False
        ButtonDomeStop.Enabled = False
        CheckBoxTrack.Enabled = False
        Form1.CheckBoxDT.Enabled = CheckBoxTrack.Enabled
        TimerTrack.Enabled = False
        ButtonMoveCCW.Enabled = False
        ButtonMoveCW.Enabled = False
        ButtonLocate.Enabled = True
        PictureBoxInd.Visible = False
        ButtonDC.Enabled = False
        ButtonMoveDomeToCalc.Enabled = False
        TimerMoveAGF.Enabled = False
        TimerAGFdebug.Enabled = False
        GetAGFExtendedStatus.Enabled = False
        GetDomeWheelBias.Enabled = False
        SetDomeWheelBias.Enabled = False
        If SerialPortAGFdebug.IsOpen = True Then
            SerialPortAGFdebug.Close()
        End If
        ActiveCtl = CtlNone

    End Sub

    Public Sub AGFnetworkConnect()
        If SocketIsOpen = False Then
            Me.Cursor = Cursors.WaitCursor
            Try
                UpdateStatusLine("Connecting to AGF Dome controller, 30 second timeout", Color.Black)
                UpdateStatusLine("IP=" & AGFipAddress & ", Port=" & TCPdataPort, Color.Black)
                Application.DoEvents()
                tcpClient = New System.Net.Sockets.TcpClient()
                IPaddr = IPAddress.Parse(AGFipAddress)
                tcpClient.Connect(IPaddr, TCPdataPort)
                tcpClient.ReceiveTimeout = AGFtimeoutTCP
                networkStream = tcpClient.GetStream
                SocketIsOpen = True
                ActiveCtl = CtlAGF
                SendCommand(":I#")
                If DomeResponse = "" Then
                    UpdateStatusLine("No response from AGF dome controller", Color.DarkRed)
                    tcpClient.Close()
                    SocketIsOpen = False
                Else
                    If Mid(DomeResponse, 1, 3) = "(A)" Then
                        AGFarduino = True
                        GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = True
                    Else
                        AGFarduino = False
                        GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = False
                    End If
                    TimerAGFdiag.Enabled = False
                    AGFdomeEmulatorMode.Checked = False
                    StartComDiag.Checked = False
                    If DebugAGF.Checked = True Then
                        SetDebugAGF(True)
                    End If
                    DomeConnected = True
                    ButtonAGFconnect.Text = "Disconnect"
                    ButtonDomeConnect.Enabled = False
                    ButtonLocate.Enabled = False
                    ButtonDomeGoto.Enabled = True
                    ButtonDomeStop.Enabled = True
                    ButtonMoveCCW.Enabled = True
                    ButtonMoveCW.Enabled = True
                    ButtonDomeSync.Enabled = ButtonGetAz.Enabled
                    CheckBoxTrack.Enabled = ButtonGetAz.Enabled
                    Form1.CheckBoxDT.Enabled = CheckBoxTrack.Enabled
                    ButtonLocate.Enabled = False
                    Form_ControlP.ButtonDomeTest.Enabled = True
                    InitializeAGFDomeController.Enabled = True
                    AGFdomeEmulatorMode.Enabled = True
                    StartComDiag.Enabled = True
                    GetAGFExtendedStatus.Enabled = True
                    GetDomeWheelBias.Enabled = True
                    SetDomeWheelBias.Enabled = True
                    DebugAGF.Enabled = True
                    PictureBoxInd.Visible = True
                    If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
                        ButtonDC.Enabled = True
                        ButtonMoveDomeToCalc.Enabled = True
                        If ConnectDSRport.Checked = True Then
                            GetDSRcheckState()
                        End If
                    End If
                    UpdateStatusLine("Connected Network " & DomeResponse, Color.Black)
                End If

            Catch ex As Exception
                UpdateStatusLine("Connect error: '" & ex.Message & "'", Color.DarkRed)
            End Try

        Else

            SendCommand(":I#")
            GetDomePositionFromDomeControllerToolStripMenuItem.Enabled = False
            tcpClient.Close()
            SocketIsOpen = False
            ActiveCtl = CtlNone
            DomeConnected = False
            CheckBoxTrack.Checked = False
            TimerDomeMoveAGF.Enabled = False
            TimerAGFdiag.Enabled = False
            AGFdomeEmulatorMode.Checked = False
            AGFdomeEmulatorMode.Enabled = False
            Form_ControlP.ButtonDomeTest.Enabled = False
            InitializeAGFDomeController.Enabled = False
            AGFdomeEmulatorMode.Enabled = False
            StartComDiag.Enabled = False
            StartComDiag.Checked = False
            DebugAGF.Enabled = False
            SetAGFportClosed()
            UpdateStatusLine("Disconnected Network", Color.Black)
        End If

        Me.Cursor = Cursors.Default
        Application.DoEvents()

    End Sub

    Public Sub ButtonSetDomeAGF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSetDomeAGF.Click
        SetDomeAGFpos()

    End Sub

    Public Sub SetDomeAGFpos()
        TrackBarDomePos.Value = TrackBarDome.Value
        LabelTdome.Text = TBdomeAz & TrackBarDome.Value
        DomeRotate = TrackBarDome.Value
        If AGFarduino = True Then
            SendCommand(":S" & DomeRotate & "#")
        End If
        PictureBoxDome.Refresh()
        UpdateStatusLine("Dome position set to dome azimuth slider of " & DomeRotate & "°", Color.Black)

    End Sub

    Private Sub ButtonSetPosAGF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSetPosAGF.Click
        TrackBarDome.Value = TrackBarScope.Value
        TrackBarDomePos.Value = TrackBarScope.Value
        LabelTdome.Text = TBdomeAz & TrackBarScope.Value
        DomeRotate = TrackBarDome.Value
        If AGFarduino = True Then
            SendCommand(":S" & DomeRotate & "#")
        End If
        PictureBoxDome.Refresh()
        UpdateStatusLine("Dome position set to mount position of " & DomeRotate & "°", Color.Black)

    End Sub

    Private Sub ButtonSetCalcAGF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSetCalcAGF.Click
        Try
            TrackBarDome.Value = DomeCalcAz
            TrackBarDomePos.Value = DomeCalcAz
            LabelTdome.Text = TBdomeAz & DomeCalcAz
            DomeRotate = TrackBarDome.Value
            If AGFarduino = True Then
                SendCommand(":S" & DomeRotate & "#")
            End If
            PictureBoxDome.Refresh()
            UpdateStatusLine("Dome position set to calc position of " & DomeRotate & "°", Color.Black)

        Catch ex As Exception
            UpdateStatusLine("DomeCalcAZ incorrect " & ex.Message, Color.DarkRed)

        End Try

    End Sub

    Private Sub TimerMoveAGF_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerMoveAGF.Tick
        TimerDomeMoveAGF.Enabled = False
        TimerMoveAGF.Enabled = False
        DomeMovingAGF = False
        If AGFtimedmove = False Then
            SendCommand(DomeAGFstop)
        End If
        Dim I As Integer = TrackBarDome.Value
        TrackBarDomePos.Value = I
        LabelTdome.Text = TBdomeAz & I
        DomeRotate = I
        PictureBoxDome.Refresh()
        DomeCurAz = TrackBarDomePos.Value
        Dim S As String = StatusLabel.Text & ", complete"
        UpdateStatusLine("AGF dome move complete", Color.Black)
        StatusLabel.Text = S
        If CheckBoxTrack.Checked = True Then
            TimerTrack.Enabled = True
        End If

    End Sub

    Private Sub TimerDomeMoveAGF_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerDomeMoveAGF.Tick
        Dim TimeNow, TimeOfMove As Single

        TimeNow = Microsoft.VisualBasic.DateAndTime.Timer
        TimeOfMove = TimeNow - TimeStart
        DegOfMove = MaskedTextBoxDegSec.Text / 100 * TimeOfMove
        If DomeDirectionAGF = 1 Then
            UpdateDomePicAGF(DomeStartPosAGF + DegOfMove)
        Else
            UpdateDomePicAGF(DomeStartPosAGF - DegOfMove)
        End If
        DomeCurAz = TrackBarDomePos.Value

    End Sub

    Private Sub UpdateStatusLine(ByVal Line As String, ByVal Color As Color)
        StatusLabel.Text = Line
        If NoDupStatusEntries.Checked = True And PrevStatus = Line And DupLogCheck = True Then
        Else
            LogDome("Status = ", Color, Line)
        End If
        PrevStatus = Line

    End Sub

    Private Sub DomesFilenameToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DomesFilenameToolStripMenuItem.Click
        StatusLabel.Text = Form1.DomeFilename

    End Sub

    Private Sub EditObservatoriesDomesFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles EditObservatoriesDomesFileToolStripMenuItem.Click
        Shell("Notepad " & Form1.DomeFilename, AppWinStyle.NormalFocus)
        StatusLabel.Text = "Open Domes File to apply edited changes"

    End Sub

    Private Sub OpenObservatoriesCustomeDomeFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenObservatoriesCustomeDomeFileToolStripMenuItem.Click
        Dim Ipath As String = Path.GetDirectoryName(Form1.DomeFilename)
        OpenFileDialog1.InitialDirectory = Ipath
        OpenFileDialog1.Filter = "Dome files|*.txt"
        If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
            Form1.DomesFileCustom = OpenFileDialog1.FileName
            Form1.DomeCurrent = 0
            Form1.Load_Domes()
            UpdateStatusLine("Domes file loaded: " & Form1.DomesFileCustom, Color.Black)
        End If

    End Sub

    Private Sub ResetDomesFileToDefaultToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ResetDomesFileToDefaultToolStripMenuItem.Click
        Form1.DomesFileCustom = ""
        Form1.DomeCurrent = 0
        Form1.Load_Domes()
        UpdateStatusLine("Default domes file loaded", Color.Black)

    End Sub

    Private Sub ClearStatusLineToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ClearStatusLineToolStripMenuItem.Click
        StatusLabel.Text = ""

    End Sub

    Private Sub NumericUpDownMD_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles NumericUpDownMD.ValueChanged
        Select Case NumericUpDownMD.Value
            Case 0
                LabelMD.Text = "None"
            Case 1
                LabelMD.Text = "West 1"
            Case 2
                LabelMD.Text = "West 2"
            Case -1
                LabelMD.Text = "East 1"
            Case -2
                LabelMD.Text = "East 2"
        End Select

    End Sub

    Private Sub DebugLogging_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DebugLogging.Click
        If DebugLogging.Checked = True Then
            DebugLogging.Checked = False
            DebugLog = False
            UpdateStatusLine("Debug logging disabled", Color.Black)
        Else
            DebugLogging.Checked = True
            DebugLog = True
            UpdateStatusLine("Debug logging enabled", Color.Black)
        End If

    End Sub

    Private Sub LogDebug(ByVal Line As String)
        LogDome("Debug = ", Color.SaddleBrown, Line)

    End Sub

    Public Sub LogDome(ByVal EntryType As String, ByVal EntryColor As Color, ByVal EntryLine As String)
        If Form_DOME_SENT_RESP_LOG.CheckBoxPause.Checked = False Then
            Dim D As TimeSpan = Now.TimeOfDay
            T = Format(D.Hours, "00") & ":" & Format(D.Minutes, "00") & ":" & Format(D.Seconds, "00") & _
                "." & Format(D.Milliseconds, "000") & "  "
            Form_DOME_SENT_RESP_LOG.RichTextBox1.SelectionColor = EntryColor
            Form_DOME_SENT_RESP_LOG.RichTextBox1.SelectedText = T & EntryType & EntryLine
            If EntryColor = Color.DarkRed Then
                Form_DOME_SENT_RESP_LOG.RichTextBox2.SelectionColor = EntryColor
                Form_DOME_SENT_RESP_LOG.RichTextBox2.SelectedText = T & EntryType & EntryLine
            End If
        End If

    End Sub

    Private Sub TimerAGFwait_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerAGFwait.Tick
        SendCommand(":I#")
        If DomeResponse <> "" Then
            TimerAGFwait.Enabled = False
            UpdateStatusLine("AGF dome connection reestablished", Color.Black)
            If Form1.AutoDomeTrackStartup.Checked = True Then
                Talker.SpeakAsync("AGF dome connection has been reestablished and auto dome tracking started")
            End If
            CheckBoxTrack.Checked = True
            ConnectDSRport.Checked = DSRswitchset
        End If

    End Sub

    Private Sub TimerDSR_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerDSR.Tick
        Dim Line As String = ""
        Dim PinChange As Boolean = False

        If DomeConnected = False Then Exit Sub

        TimerDSRcount = TimerDSRcount + 1
        'UpdateStatusLine("TimerDSR Tick = " & TimerDSRcount, Color.OrangeRed)

        DSRstate = SerialPort3.DsrHolding

        If DSRstate <> DSRswitchLast Then
            DSRswitch = True
            If DSRstate = -1 Then
                LabelDsr.Text = "= True"

                If TimerDSRignore = False Then
                    If CheckBoxTrack.Enabled = True And ButtonDC.Enabled = True Then
                        If TimerDSRcount > 1 Then
                            ButtonDC.PerformClick()
                            ButtonSetCalcAGF.PerformClick()
                            Line = "Dome tracking enabled, dome azimuth " & DomeCalcAz & " degrees"
                        Else
                            TrackBarDome.Value = Form1.DomeLastPos
                            Line = "Dome tracking resumed, dome azimuth " & Form1.DomeLastPos & " degrees"
                        End If
                        CheckBoxTrack.Checked = True
                        Talker.SpeakAsync(Line)
                        UpdateStatusLine(Line & " > DSR " & LabelDsr.Text, Color.Black)
                    End If
                End If
            Else
                LabelDsr.Text = "= False"
                If TimerDSRignore = False Then
                    If CheckBoxTrack.Checked = True Then
                        CheckBoxTrack.Checked = False
                        Line = "Dome tracking disabled"
                        Talker.SpeakAsync(Line)
                        UpdateStatusLine(Line & " > DSR " & LabelDsr.Text, Color.Black)
                    End If
                End If
            End If
            DSRswitch = False
        End If
        DSRswitchLast = DSRstate
        DSRstart = False

        CTSstate = SerialPort3.CtsHolding

        ' Check rs232 pins CD, CTS, RI
        If SigPin <> SigPinPrev Then
            Select Case SigPin
                Case IO.Ports.SerialPinChange.CtsChanged, IO.Ports.SerialPinChange.Ring
                    If CTSstate = True Then
                        If EWswCP3MeridianDelay = False Then
                            NumericUpDownMD.Value = 0
                            Line = "Meridian delay cleared"
                        Else
                            Form_Meridian.SetMeridianOffset(True)
                            NumericUpDownMD.Value = 0
                            Line = "Meridian delay cleared"
                        End If
                    Else
                        If EWswCP3MeridianDelay = False Then
                            NumericUpDownMD.Value = 1
                            Line = "Meridian delay West 1 hour"
                        Else
                            Form_Meridian.MerWest.Checked = True
                            Form_Meridian.SetMeridianOffset(False)
                            NumericUpDownMD.Value = 0
                            FormatMer()
                            Line = "Meridian offset West " & MerFmt
                        End If
                    End If
                    Talker.SpeakAsync(Line)
                    UpdateStatusLine(Line, Color.Black)

                Case IO.Ports.SerialPinChange.CDChanged
                    If EWswCP3MeridianDelay = False Then
                        NumericUpDownMD.Value = -1
                        Line = "Meridian delay East 1 hour"
                    Else
                        Form_Meridian.MerEast.Checked = True
                        Form_Meridian.SetMeridianOffset(False)
                        NumericUpDownMD.Value = 0
                        FormatMer()
                        Line = "Meridian offset East " & MerFmt
                    End If
                    Talker.SpeakAsync(Line)
                    UpdateStatusLine(Line, Color.Black)

            End Select
            PinChange = True
            SigPinPrev = SigPin
        End If

        If PinChange = False Then
            If CTSstate <> CTSstateLast Then
                If EWswCP3MeridianDelay = False Then
                    If CTSstate = True Then
                        NumericUpDownMD.Value = 0
                        Line = "Meridian delay cleared"
                    Else
                        NumericUpDownMD.Value = 1
                        Line = "Meridian delay West 1 hour"
                    End If
                Else
                    If CTSstate = False Then
                        Form_Meridian.MerWest.Checked = True
                        Form_Meridian.SetMeridianOffset(False)
                        NumericUpDownMD.Value = 0
                        FormatMer()
                        Line = "Meridian offset West " & MerFmt
                    Else
                        Form_Meridian.SetMeridianOffset(True)
                        NumericUpDownMD.Value = 0
                        Line = "Meridian offset cleared"
                    End If

                End If
                Talker.SpeakAsync(Line)
                UpdateStatusLine(Line, Color.Black)
            End If
        End If

        ' Check for brake sent via push button
        If TimerDSRignore = False Then
            If SigPin = IO.Ports.SerialPinChange.Break And PinChangedEntered = True And ComBreakIssued = True Then
                TimerDSRignore = True
                If BreakTypeClose = True Then
                    Talker.SpeakAsync("closing connections")
                    BreakTypeClose = False
                    If SerialPort2.IsOpen = True Or SocketIsOpen = True Then
                        ButtonAGFconnect.PerformClick()
                    End If
                    If Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
                        Form1.ButtonConnect.PerformClick()
                    End If
                    If Form1.SerialPort1.IsOpen = True Or SerialPort2.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True Then
                        BreakTypeClose = True
                        Line = "Disconnecting from mount or dome controller failed"
                    Else
                        BreakTypeClose = False
                        Line = "Disconnected from mount and dome controller"
                    End If
                    'Thread.Sleep(5000)
                Else
                    Line = ""
                    Talker.SpeakAsync("opening connections")
                    If Form1.SerialPort1.IsOpen = False Or Form1.SocketIsOpen = False Or Form1.IsConnected = False Then
                        Form1.ButtonConnect.PerformClick()
                    End If
                    If SerialPort2.IsOpen = False Then
                        ButtonAGFconnect.PerformClick()
                    End If
                    If (Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True) _
                        And (SerialPort2.IsOpen = True Or SocketIsOpen = True) Then
                        BreakTypeClose = True
                        Line = "Now reconnected to mount and dome controller"
                    Else
                        BreakTypeClose = False
                        If (Form1.SerialPort1.IsOpen = False Or Form1.SocketIsOpen = False Or Form1.IsConnected = False) Then
                            Line = "Reconnecting failed to mount. "
                        End If
                        If (SerialPort2.IsOpen = False Or SocketIsOpen = False) Then
                            Line = Line & "Reconnecting failed to dome controller"
                        End If
                    End If
                End If
                ConnectDSRport.Checked = True
                Talker.SpeakAsync(Line)
                UpdateStatusLine("DSR Break - " & Line, Color.Black)
                TimerDSRignore = False
            End If
        End If

        CTSstateLast = CTSstate

        Dim CTStext As String
        If CTSstate = True Then
            CTStext = " = True"
        Else
            CTStext = " = Flase"
        End If
        If DebugLog = True And PinChangedEntered = True Then
            Select Case SigPin
                Case IO.Ports.SerialPinChange.Break
                    LogDebug("SigPin changed " & SigPin & " Break")
                    LogDebug("Break button press = " & BreakChars)
                Case IO.Ports.SerialPinChange.CDChanged
                    LogDebug("SigPin changed " & SigPin & " CD")
                Case IO.Ports.SerialPinChange.CtsChanged
                    LogDebug("SigPin changed " & SigPin & " CTS " & CTStext)
                Case IO.Ports.SerialPinChange.DsrChanged
                    LogDebug("SigPin changed " & SigPin & " DSR " & LabelDsr.Text)
                Case IO.Ports.SerialPinChange.Ring
                    LogDebug("SigPin changed " & SigPin & " Ring")
                Case Else
                    LogDebug("SigPin changed " & SigPin)
            End Select
        End If

        PinChangedEntered = False

    End Sub

    Private Sub FormatMer()
        Dim M As String()
        M = Split(Form1.MeridianOffset, ":")
        MerFmt = ""
        If M(0) <> 0 Then
            MerFmt = M(0) & " Hour "
            MerFmt = MerFmt.Replace("-", "")
        End If
        If M(1) <> 0 Then
            MerFmt = MerFmt & ", " & M(1) & " Minutes "
        End If

    End Sub

    Private Sub ConnectDSRport_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectDSRport.CheckedChanged
        GetDSRcheckState()

    End Sub

    Private Sub GetDSRcheckState()
        If ConnectDSRport.Checked = False Then
            If SerialPort3.IsOpen = True Then
                TimerDSR.Enabled = False
                LabelDsr.Text = ""
                SerialPort3.Close()
                ComboboxAGFdsrCom.Enabled = True
                UpdateStatusLine("DSR port closed", Color.Black)
            End If
        Else
            If SerialPort3.IsOpen = False Then
                Try
                    SerialPort3.PortName = DSRportName
                    SerialPort3.Open()
                    ComboboxAGFdsrCom.Enabled = False
                    DSRstart = True
                    TimerDSR.Enabled = True
                    ConnectDSRport.Checked = True
                    UpdateStatusLine("DSR port opened " & SerialPort3.PortName, Color.Black)
                Catch ex As Exception
                    UpdateStatusLine("Error opening DSR port, " & ex.Message, Color.DarkRed)
                    ConnectDSRport.Checked = False
                End Try
            End If
        End If
        DSRswitchLast = -2

    End Sub

    Private Sub SerialPort3_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort3.DataReceived
        BreakChars = SerialPort3.BytesToRead

    End Sub

    Private Sub SerialPort3_PinChanged(ByVal sender As Object, ByVal e As System.IO.Ports.SerialPinChangedEventArgs) Handles SerialPort3.PinChanged
        SigPin = e.EventType
        If SigPin = IO.Ports.SerialPinChange.Break Then
            If FirstBreak = False Then
                FirstBreak = True
                Exit Sub
            Else
                FirstBreak = False
            End If
            ComBreakIssued = True
            My.Computer.Audio.Play(My.Resources.ding, AudioPlayMode.WaitToComplete)
            If (Form1.SerialPort1.IsOpen = True Or Form1.SocketIsOpen = True Or Form1.IsConnected = True) And (SerialPort2.IsOpen = True Or SocketIsOpen = True) Then
                BreakTypeClose = True
            End If
        Else
            ComBreakIssued = False
        End If
        PinChangedEntered = True

    End Sub

    Private Sub NoDupStatusEntries_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NoDupStatusEntries.Click
        If NoDupStatusEntries.Checked = True Then
            NoDupStatusEntries.Checked = False
        Else
            NoDupStatusEntries.Checked = True
        End If
    End Sub

    Private Sub StartComDiag_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartComDiag.Click
        If StartComDiag.Checked = False Then
            SendCommand(":E1#")
            AGFdomeEmulatorMode.Checked = True
            AGFdomeEmulatorMode.Enabled = False
            AGFcomDiagLen = -1
            TimerAGFdiag.Interval = 250
            TimerAGFdiag.Enabled = True
            StartComDiag.Checked = True
            UpdateStatusLine("AGF Com diagnostics started", Color.Black)
        Else
            TimerAGFdiag.Enabled = False
            StartComDiag.Checked = False
            UpdateStatusLine("AGF Com diagnostics stopped", Color.Black)
            SendCommand(":E0#")
            AGFdomeEmulatorMode.Checked = False
            AGFdomeEmulatorMode.Enabled = True
        End If

    End Sub

    Private Sub TimerAGFdiag_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerAGFdiag.Tick
        TimerAGFdiag.Interval = 5000
        SendCommand(":V#")
        If AGFcomDiagLen = -1 Then
            AGFcomDiagLen = DomeResponse.Length
        End If
        If AGFcomDiagLen <> DomeResponse.Length Then
            UpdateStatusLine("AGF Com diag. response length error, expected=" & AGFcomDiagLen _
                & " received=" & DomeResponse.Length, Color.DarkRed)
        End If

    End Sub

    Private Sub AGFdomeEmulatorMode_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AGFdomeEmulatorMode.Click
        If AGFdomeEmulatorMode.Checked = False Then
            AGFdomeEmulatorMode.Checked = True
            SendCommand(":E1#")
            UpdateStatusLine("AGF Dome Controller Emulator mode On", Color.Black)
        Else
            AGFdomeEmulatorMode.Checked = False
            SendCommand(":E0#")
            UpdateStatusLine("AGF Dome Controller Emulator mode Off", Color.Black)
        End If

    End Sub

    Private Sub InitializeAGFDomeController_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles InitializeAGFDomeController.Click
        SendCommand(":I#")

    End Sub

    Private Sub ParkDomeButton_Click(sender As System.Object, e As System.EventArgs) Handles ParkDomeButton.Click
        Select Case ActiveCtl
            Case CtlAGF
                If SerialPort2.IsOpen Or SocketIsOpen = True Then
                    ParkDome()
                End If
            Case CtlNCO
                If SocketIsOpen = True Then
                    ParkDome()
                End If
            Case Else
                UpdateStatusLine("Dome Controller not connected", Color.Black)
        End Select
    End Sub

    Public Sub ParkDome()
        If CheckBoxTrack.Checked = True Then
            CheckBoxTrack.Checked = False
        End If
        TrackBarDome.Value = ParkPos
        ButtonDomeGoto.PerformClick()
        UpdateStatusLine("Dome moving to park position " & ParkPos & "° ", Color.Black)

    End Sub

    Private Sub ComboBoxDomePark_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ComboBoxDomePark.SelectedIndexChanged
        ParkPos = Mid(ComboBoxDomePark.SelectedItem, 1, 3)
        ParkDomeButton.ToolTipText = "Move dome to " & ParkPos & "°"

    End Sub

    Private Sub DurTimerParksDome_Click(sender As System.Object, e As System.EventArgs) Handles DurTimerParksDome.Click
        If DurTimerParksDome.Checked = False Then
            DurTimerParksDome.Checked = True
        Else
            DurTimerParksDome.Checked = False
        End If

    End Sub

    Private Sub ButtonEWSwitchDoesCP3MeridianDelay_Click(sender As System.Object, e As System.EventArgs) Handles ButtonEWSwitchDoesCP3MeridianDelay.Click
        If ButtonEWSwitchDoesCP3MeridianDelay.Checked = True Then
            ButtonEWSwitchDoesCP3MeridianDelay.Checked = False
        Else
            ButtonEWSwitchDoesCP3MeridianDelay.Checked = True
        End If
        EWswCP3MeridianDelay = ButtonEWSwitchDoesCP3MeridianDelay.Checked
        Form1.EWswitchCP3MeridianDelay = ButtonEWSwitchDoesCP3MeridianDelay.Checked

    End Sub

    Private Sub StopTrackingOnTimeout_Click(sender As System.Object, e As System.EventArgs) Handles StopTrackingOnTimeout.Click
        If StopTrackingOnTimeout.Checked = True Then
            StopTrackingOnTimeout.Checked = False
        Else
            StopTrackingOnTimeout.Checked = True
        End If

    End Sub


    Private Sub ToolStripMenuItem2_Click(sender As System.Object, e As System.EventArgs) Handles ToolStripMenuItem2.Click
        AGFipAddress = AGFip.Text
        UpdateStatusLine("AGF Dome Controller IP address set to " & AGFipAddress, Color.Black)

    End Sub

    Private Sub ComboBoxAGFtimeout_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ComboBoxAGFtimeout.SelectedIndexChanged
        AGFtimeoutTCP = (ComboBoxAGFtimeout.SelectedIndex + 1) * 1000

    End Sub

    Private Sub ComboboxAGFdsrCom_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ComboboxAGFdsrCom.SelectedIndexChanged
        DSRportName = Trim(Microsoft.VisualBasic.Left(ComboboxAGFdsrCom.Items(ComboboxAGFdsrCom.SelectedIndex), 6))
        If DSRportName = "None" Then
            ConnectDSRport.Enabled = False
        Else
            ConnectDSRport.Enabled = True
        End If

    End Sub

    Private Sub ComboBoxAGFdebugCom_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ComboBoxAGFdebugCom.SelectedIndexChanged
        AGFdebugPortName = Trim(Microsoft.VisualBasic.Left(ComboBoxAGFdebugCom.Items(ComboBoxAGFdebugCom.SelectedIndex), 6))

    End Sub

    Private Sub DomeConfigurationSettingsToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles DomeConfigurationSettingsToolStripMenuItem.Click
        Dim Config As String = ComboBoxDomes.SelectedItem
        If Config = Nothing Then
            StatusLabel.Text = "Dome config not set"
        Else
            Dim C() As String
            Dim Fmt As String
            Dim EWoffset As String = "West<"
            C = Split(Config, ",")
            If C(3) < 0 Then
                EWoffset = "East>"
            End If
            Fmt = C(0) & ",  " & C(1) & "m,  " & C(2) & "ota^,  " & C(4) & "mnt.^,  " & C(3) & EWoffset
            StatusLabel.Text = Fmt
            LogDome("Config = ", Color.Black, Fmt)
        End If

    End Sub

    Private Sub ButtonAGFencoder_Click(sender As System.Object, e As System.EventArgs) Handles ButtonAGFencoder.Click
        If ButtonAGFencoder.Checked = True Then
            ButtonAGFencoder.Checked = False
        Else
            ButtonAGFencoder.Checked = True
        End If
    End Sub

    Private Sub DebugAGF_Click(sender As System.Object, e As System.EventArgs) Handles DebugAGF.Click
        If DebugAGF.Checked = False Then
            SetDebugAGF(True)
        Else
            SetDebugAGF(False)
        End If

    End Sub

    Private Sub SetDebugAGF(ByVal State As Boolean)
        If State = True Then
            SendCommand(":D1#")
            DebugAGF.Checked = True
            If AGFdebugPortName <> "None" Then
                AGFdebugData = ""
                Try
                    SerialPortAGFdebug.PortName = AGFdebugPortName
                    SerialPortAGFdebug.Open()
                    TimerAGFdebug.Enabled = True
                    LogDome("Debug = ", Color.DarkMagenta, "Port open " & AGFdebugPortName)
                Catch ex As Exception
                    UpdateStatusLine("AGF debug port error: '" & ex.Message & "'", Color.DarkRed)
                End Try
            End If
        Else
            SendCommand(":D0#")
            DebugAGF.Checked = False
            TimerAGFdebug.Enabled = False
            If SerialPortAGFdebug.IsOpen = True Then
                SerialPortAGFdebug.Close()
                LogDome("Debug = ", Color.DarkMagenta, "Port closed " & AGFdebugPortName)
            End If
        End If

    End Sub

    Private Sub TimerAGFdebug_Tick(sender As System.Object, e As System.EventArgs) Handles TimerAGFdebug.Tick
        AGFdebugData = AGFdebugData & SerialPortAGFdebug.ReadExisting
        If Microsoft.VisualBasic.Right(AGFdebugData, 1) = vbCr Then
            AGFdebugData = AGFdebugData.Replace(vbCr, " | ")
            UpdateStatusLine(AGFdebugData, Color.DarkMagenta)
            AGFdebugData = ""
        End If

    End Sub

    Public Sub DisconnectDome()
        If DomeConnected = True Then
            If ActiveCtl = CtlNCO Then
                ButtonDomeConnect.PerformClick()
            End If
            If ActiveCtl = CtlAGF Then
                ButtonAGFconnect.PerformClick()
            End If
        End If

    End Sub

    Private Sub TrackBarDomePos_ValueChanged(sender As Object, e As System.EventArgs) Handles TrackBarDomePos.ValueChanged
        If DomeCalcAz < 0 Then
            LabelCalc.Text = "N/A"
        Else
            LabelCalc.Text = Format(DomeCalcAz, "000")
        End If
        LabelDomeAz.Text = Format(TrackBarDomePos.Value, "000")

    End Sub

    Private Sub OpenObservatoriesDomeFileLocationToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles OpenObservatoriesDomeFileLocationToolStripMenuItem.Click
        Dim Cmd As String
        Dim Ipath As String = Path.GetDirectoryName(Form1.DomeFilename)
        Cmd = "Explorer /e, " & Ipath
        Shell(Cmd, AppWinStyle.NormalFocus)

    End Sub

    Private Sub StatusLabel_TextChanged(sender As Object, e As System.EventArgs) Handles StatusLabel.TextChanged
        Form1.TextBoxDome.Text = StatusLabel.Text

    End Sub

    Private Sub ReloadCurrentObservatoryDomeFileToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ReloadCurrentObservatoryDomeFileToolStripMenuItem.Click
        Form1.Load_Domes()

    End Sub

    Private Sub GetDomePositionFromDomeControllerToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles GetDomePositionFromDomeControllerToolStripMenuItem.Click
        SendCommand(":G#")
        If DomeResponse <> "" Then
            UpdateStatusLine(DomeResponse, Color.Black)
        End If

    End Sub

    Private Sub GetDomeWheelBias_Click(sender As System.Object, e As System.EventArgs) Handles GetDomeWheelBias.Click
        SendCommand(":A#")
        If DomeResponse <> "" Then
            UpdateStatusLine(DomeResponse, Color.Black)
        End If

    End Sub

    Private Sub SetDomeWheelBias_Click(sender As System.Object, e As System.EventArgs) Handles SetDomeWheelBias.Click
        Try
            Dim DomeBias As String
            Dim Bias As Integer
            Bias = TextBoxDomeWheelBias.Text
            DomeBias = ":B" & Format(Bias, "000") & "#"
            SendCommand(DomeBias)
            If DomeResponse <> "" Then
                UpdateStatusLine(DomeResponse, Color.Black)
            End If
        Catch ex As Exception
            UpdateStatusLine("Bias value error '" & ex.Message & "'", Color.DarkRed)

        End Try

    End Sub

    Private Sub GetAGFExtendedStatus_Click(sender As System.Object, e As System.EventArgs) Handles GetAGFExtendedStatus.Click
        SendCommand(":X#")
        If DomeResponse <> "" Then
            UpdateStatusLine(DomeResponse, Color.Black)
        End If

    End Sub
End Class

