Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Threading
Imports ximc

Namespace test_VBNET
    Class testapp
        Public Shared Sub print_status(ByVal status As status_t)
            Console.WriteLine("Status:")
            Console.Write(" rpm: {0},", status.CurSpeed)
            Console.Write(" pos: {0},", status.CurPosition)
            Console.Write(" upwr: {0},", status.Upwr)
            Console.Write(" ipwr: {0},", status.Ipwr)
            Console.Write(" flags: {0}", status.Flags)
            Console.Write(" mvsts: {0}", status.MvCmdSts)
            If (status.Flags And CUInt(Flags.STATE_ALARM)) <> 0 Then
                Console.Write(", ALARM")
            End If

            If (status.Flags And CUInt(Flags.STATE_ERRC)) <> 0 Then
                Console.Write(", ERRC")
            End If

            If (status.Flags And CUInt(Flags.STATE_ERRD)) <> 0 Then
                Console.Write(", ERRD")
            End If

            Console.Write(vbLf)
        End Sub

        Public Shared Function error_string(ByVal result As Result) As String
            Select Case result
                Case result.error
                    Return "error"
                Case result.not_implemented
                    Return "not implemented"
                Case result.no_device
                    Return "no device"
                Case result.value_error
                    Return "value error"
                Case Else
                    Return "success"
            End Select
        End Function

        Private Shared Sub get_status_and_print(ByVal device As Integer)
            Dim res As Result
            Dim status As status_t = Nothing
            res = API.get_status(device, status)
            If res <> Result.ok Then
                Console.WriteLine("Error getting status: {0}", error_string(res))
            Else
                print_status(status)
            End If
        End Sub

        Public Shared Sub print_status_calb(ByVal status As status_calb_t)
            Console.WriteLine("Status calb:")
            Console.Write(" rpm: {0},", status.CurSpeed)
            Console.Write(" pos: {0},", status.CurPosition)
            Console.Write(" upwr: {0},", status.Upwr)
            Console.Write(" ipwr: {0},", status.Ipwr)
            Console.Write(" flags: {0},", status.Flags)
            Console.Write(" mvsts: {0}", status.MvCmdSts)
            If (status.Flags And CUInt(Flags.STATE_ALARM)) <> 0 Then
                Console.Write(", ALARM")
            End If

            If (status.Flags And CUInt(Flags.STATE_ERRC)) <> 0 Then
                Console.Write(", ERRC")
            End If

            If (status.Flags And CUInt(Flags.STATE_ERRD)) <> 0 Then
                Console.Write(", ERRD")
            End If

            Console.Write(vbLf)
        End Sub

        Public Shared Function search_devices(<Out> ByRef device_count As Integer) As IntPtr
            Console.WriteLine(vbLf & "Searching for devices...")
            Dim probe_flags As Integer = CInt(Flags.ENUMERATE_PROBE Or Flags.ENUMERATE_NETWORK)
            Const enumerate_hints As String = "addr="
            Dim devenum As IntPtr = API.enumerate_devices(probe_flags, enumerate_hints)
            If devenum = IntPtr.Zero Then
                Console.WriteLine("Error searching for devices")
                device_count = 0
                Return devenum
            End If

            device_count = API.get_device_count(devenum)
            If device_count < 1 Then
                Console.WriteLine("No devices found")
                Return devenum
            End If

            Console.WriteLine("Found {0} devices", device_count + 1)
            Return devenum
        End Function

        Public Shared Sub print_device_list(ByVal devenum As IntPtr, ByVal device_count As Integer)
            Console.WriteLine(vbLf & "Found devices list:")
            Dim i As Integer = 0
            For i = 0 To device_count - 1
                Dim device_name As String = API.get_device_name(devenum, i)
                Console.WriteLine(" #{0}. {1}", i + 1, device_name)
            Next
            Console.WriteLine(" #{0}. virtual", device_count + 1)
        End Sub

        Public Shared Function create_virtual_device_name() As String
            Dim home_path As String = Environment.GetEnvironmentVariable("USERPROFILE")
            Dim file_path As String = Path.Combine(home_path, "virt_controller.bin")
            Dim device_name As String = "xi-emu:///" & file_path
            Console.WriteLine("Virtual controller file path: '{0}'", file_path)
            Return device_name
        End Function

        Public Shared Function get_device_name_from_list(ByVal devenum As IntPtr, ByVal device_count As Integer) As String
            While True
                print_device_list(devenum, device_count)
                Console.WriteLine(vbLf & "When using an Ethernet (TCP protocol) connection, multi-user interaction with the device is possible. In this case, the same device may be controlled simultaneously from multiple sources, which can potentially lead to control conflicts.")
                Console.WriteLine("Enter device number from the list:")
                Dim input As String = Console.ReadLine()
                Dim number As Integer
                If Not Integer.TryParse(input, number) Then
                    Continue While
                End If

                If 1 <= number AndAlso number <= device_count Then
                    Dim device_name As String = API.get_device_name(devenum, number - 1)
                    Console.WriteLine("Selected device: '{0}'", device_name)
                    Return device_name
                End If

                If number = device_count + 1 Then
                    Return create_virtual_device_name()
                End If
            End While

            Return ""
        End Function

        Public Shared Function choose_device() As String
            Dim device_count As Integer
            Dim devenum As IntPtr = search_devices(device_count)
            Dim device_name As String = ""
            If device_count < 1 Then
                Console.WriteLine("The real controller is not found or busy with another app.")
                Console.WriteLine("The virtual controller is opening to check the operation of the library...")
                device_name = create_virtual_device_name()
            Else
                device_name = get_device_name_from_list(devenum, device_count)
            End If

            If devenum <> IntPtr.Zero Then
                API.free_enumerate_devices(devenum)
            End If

            Return device_name
        End Function

        Public Shared Sub print_motor_type(ByVal device As Integer)
            ' Reading motor parameters and output its type.
            ' MotorType = 0 motor not defined or not connected.
            ' MotorType = 1 step.
            ' MotorType = 2 DC.
            ' MotorType = 3 BLDC.

            Dim motor_settings As motor_settings_t = Nothing
            Dim res As Result = API.get_motor_settings(device, motor_settings)
            If res <> Result.ok Then
                Console.WriteLine("Error getting motor settings: {0}", error_string(res))
            Else
                Dim motor_type_str As String
                Select Case motor_settings.MotorType
                    Case 1
                        motor_type_str = "step"
                    Case 2
                        motor_type_str = "DC"
                    Case 3
                        motor_type_str = "BLDC"
                    Case Else
                        motor_type_str = "motor not defined or not connected"
                End Select
                Console.WriteLine("Motor type: {0} ({1})", motor_settings.MotorType, motor_type_str)
            End If
        End Sub

        Public Shared Sub Main(ByVal args As String())
            Dim device As Integer = -1
            Dim res As Result
            Try
                Dim ximc_version_str As New System.Text.StringBuilder(32)
                API.ximc_version(ximc_version_str)
                Console.WriteLine("This is a ximc test program" & vbLf & "libximc version {0}", ximc_version_str.ToString())

                Dim device_name As String = choose_device()
                Console.WriteLine(vbLf & "Opening device...")
                device = API.open_device(device_name)
                If device = -1 Then
                    Console.WriteLine("Error opening device" & vbLf & "Press Enter to exit...")
                    Console.ReadLine()
                    Return
                End If

                ' Read device status
                get_status_and_print(device)

                ' Read device information
                Dim di As device_information_t = Nothing
                res = API.get_device_information(device, di)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting device information: {0}" & vbLf, error_string(res))
                Else
                    Console.WriteLine("Device information:" & vbLf & " manufacturer: {0}, id: {1}, product: {2}, version: {3}.{4}.{5}",
                        di.Manufacturer, di.ManufacturerId, di.ProductDescription, di.Major, di.Minor, di.Release)
                End If

                ' Send "zero" command to device
                res = API.command_zero(device)
                If res <> Result.ok Then
                    Console.WriteLine("Error zeroing: {0}", error_string(res))
                End If

                ' Read device status
                get_status_and_print(device)

                ' Read engine settings
                Dim engine_settings As engine_settings_t = Nothing
                res = API.get_engine_settings(device, engine_settings)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting engine settings: {0}", error_string(res))
                Else
                    Console.WriteLine("Engine settings:" & vbLf & " voltage: {0}, current: {1}, speed {2}",
                        engine_settings.NomVoltage, engine_settings.NomCurrent, engine_settings.NomSpeed)
                End If

                ' Read electromechanical settings
                Dim emf_settings As emf_settings_t = Nothing
                res = API.get_emf_settings(device, emf_settings)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting electromechanical settings: {0}", error_string(res))
                Else
                    Console.WriteLine("Electromechanical settings:" & vbLf & " Km: {0}, L: {1}, R: {2}",
                        emf_settings.Km, emf_settings.L, emf_settings.R)
                End If

                ' Read engine advanced settings
                Dim eas_settings As New engine_advanced_setup_t()
                res = API.get_engine_advanced_setup(device, eas_settings)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting engine advanced settings: {0}", error_string(res))
                Else
                    Console.WriteLine("Engine advanced settings:" & vbLf & " 1 {0}, 2 {1}, 3 {2}",
                        eas_settings.stepcloseloop_Kw, eas_settings.stepcloseloop_Kp_low, eas_settings.stepcloseloop_Kp_high)
                End If

                print_motor_type(device)

                ' Read engine calb settings
                Dim calibration As New calibration_t()
                calibration.A = 1
                calibration.MicrostepMode = Flags.MICROSTEP_MODE_FULL
                Dim engine_settings_calb As engine_settings_calb_t = Nothing
                res = API.get_engine_settings_calb(device, engine_settings_calb, calibration)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting engine calb settings: {0}", error_string(res))
                Else
                    Console.WriteLine("Engine calb settings:" & vbLf & " voltage: {0}, current: {1}, speed: {2:F3}",
                        engine_settings_calb.NomVoltage, engine_settings_calb.NomCurrent, engine_settings_calb.NomSpeed)
                End If

                Dim sec As Integer = 2
                Console.WriteLine(vbLf & "Engine rotating left for {0} seconds..." & vbLf, sec)
                res = API.command_left(device)
                If res <> Result.ok Then
                    Console.WriteLine("Error in command left: {0}", error_string(res))
                Else
                    System.Threading.Thread.Sleep(sec * 1000)
                End If

                ' Read device status
                get_status_and_print(device)

                ' Read position in user units
                Dim get_pos As get_position_calb_t = Nothing
                res = API.get_position_calb(device, get_pos, calibration)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting position in user units: {0}", error_string(res))
                Else
                    Console.WriteLine("Position in user units:" & vbLf & " pos: {0:F3}", get_pos.Position)
                End If

                ' Read device calibrated status
                Dim status_calb As status_calb_t = Nothing
                res = API.get_status_calb(device, status_calb, calibration)
                If res <> Result.ok Then
                    Console.WriteLine("Error getting calibrated state: {0}", error_string(res))
                Else
                    print_status_calb(status_calb)
                End If

                Console.WriteLine(vbLf & "Stopping engine..." & vbLf)
                res = API.command_stop(device)
                If res <> Result.ok Then
                    Console.WriteLine("Error in command stop: {0}", error_string(res))
                End If

                ' Read device status
                get_status_and_print(device)

                Console.WriteLine(vbLf & "Sleeping for {0} seconds..." & vbLf, sec)
                System.Threading.Thread.Sleep(sec * 1000)
            Catch e As Exception
                Console.WriteLine("Exception " & e.Message)
            Finally
                If device <> -1 Then
                    API.close_device(device)
                End If
            End Try
            Console.WriteLine("Done")
            Console.WriteLine("Press Enter to exit...")
            Console.ReadLine()
        End Sub
    End Class
End Namespace

