'AlignmentStationary.vb

'Gocator 2000/2300 Visual Basic Sample
'Copyright (C) 2013 by LMI Technologies Inc.

'Licensed under The MIT License.
'Redistributions of files must retain the above copyright notice.

'Purpose: Connect to Gocator system and perform stationary alignment to a flat surface

Imports System.Threading
Imports System.Runtime.InteropServices

Module AlignmentStationary
    Public Const IP As String = "192.168.1.10"
    Public Class Constants
#If DEBUG Then
        Public Const GODLLPATH As String = "GoSdk.dll"
        Public Const KAPIDLLPATH As String = "kApi.dll"
#Else
        Public Const GODLLPATH As String = "GoSdk.dll"
        Public Const KAPIDLLPATH As String = "kApi.dll"
#End If
    End Class
    Public Structure address
        Public version As Char
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)> _
        Public IPaddress() As Byte
    End Structure

    Enum kStatus
        kERROR_STATE = -1000                                                ' Invalid state.
        kERROR_NOT_FOUND = -999                                             ' Item is not found.
        kERROR_COMMAND = -998                                               ' Command not recognized.
        kERROR_PARAMETER = -997                                             ' Parameter is invalid.
        kERROR_UNIMPLEMENTED = -996                                         ' Feature not implemented.
        kERROR_HANDLE = -995                                                ' Handle is invalid.
        kERROR_MEMORY = -994                                                ' Out of memory.
        kERROR_TIMEOUT = -993                                               ' Action timed out.
        kERROR_INCOMPLETE = -992                                            ' Buffer not large enough for data.
        kERROR_STREAM = -991                                                ' Error in stream.
        kERROR_CLOSED = -990                                                ' Resource is no longer avaiable. 
        kERROR_VERSION = -989                                               ' Invalid version number.
        kERROR_ABORT = -988                                                 ' Operation aborted.
        kERROR_ALREADY_EXISTS = -987                                        ' Conflicts with existing item.
        kERROR_NETWORK = -986                                               ' Network setup/resource error.
        kERROR_HEAP = -985                                                  ' Heap error (leak/double-free).
        kERROR_FORMAT = -984                                                ' Data parsing/formatting error. 
        kERROR_READ_ONLY = -983                                             ' Object is read-only (cannot be written).
        kERROR_WRITE_ONLY = -982                                            ' Object is write-only (cannot be read). 
        kERROR_BUSY = -981                                                  ' Agent is busy (cannot service request).
        kERROR_CONFLICT = -980                                              ' State conflicts with another object.
        kERROR_OS = -979                                                    ' Generic error reported by underlying OS.
        kERROR_DEVICE = -978                                                ' Hardware device error.
        kERROR_FULL = -977                                                  ' Resource is already fully utilized.
        kERROR_IN_PROGRESS = -976                                           ' Operation is in progress, but not yet complete.
        kERROR = 0                                                          ' General error. 
        kOK = 1                                                             ' Operation successful. 
    End Enum

    Enum GoAlignmentType
        GO_ALIGNMENT_TYPE_STATIONARY = 0
        GO_ALIGNMENT_TYPE_MOVING = 1
    End Enum

    Enum GoAlignmentTarget
        GO_ALIGNMENT_TARGET_NONE = 0                                       ' No calibration target.
        GO_ALIGNMENT_TARGET_DISK = 1                                       ' Calibration disk.
        GO_ALIGNMENT_TARGET_BAR = 2                                        ' Calibration bar.
        GO_ALIGNMENT_TARGET_PLATE = 3                                      ' Calibration plate.
    End Enum

    Enum GoDataMessageTypes
        GO_DATA_MESSAGE_TYPE_UNKNOWN = -1
        GO_DATA_MESSAGE_TYPE_STAMP = 0
        GO_DATA_MESSAGE_TYPE_HEALTH = 1
        GO_DATA_MESSAGE_TYPE_VIDEO = 2
        GO_DATA_MESSAGE_TYPE_RANGE = 3
        GO_DATA_MESSAGE_TYPE_RANGE_INTENSITY = 4
        GO_DATA_MESSAGE_TYPE_PROFILE = 5
        GO_DATA_MESSAGE_TYPE_PROFILE_INTENSITY = 6
        GO_DATA_MESSAGE_TYPE_RESAMPLED_PROFILE = 7
        GO_DATA_MESSAGE_TYPE_SURFACE = 8
        GO_DATA_MESSAGE_TYPE_SURFACE_INTENSITY = 9
        GO_DATA_MESSAGE_TYPE_MEASUREMENT = 10
        GO_DATA_MESSAGE_TYPE_ALIGNMENT = 11
        GO_DATA_MESSAGE_TYPE_EXPOSURE_CAL = 12
    End Enum

    ' use DLL import to access GoSdkd.dll
    ' Note: to import the release version of the GoSdk and kApi, use GoSdk.dll and kApi.dll. GoSdkd.dll and kApid.dll are debug versions of the DLL
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSdk_Construct(ByRef assembly As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSystem_Construct(ByRef system As IntPtr, ByVal allocator As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSystem_FindSensorByIpAddress(ByVal system As IntPtr, ByVal addressPointer As IntPtr, ByRef sensor As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSystem_EnableData(ByVal system As IntPtr, ByVal enable As Boolean) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSensor_Connect(ByVal sensor As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSensor_Setup(ByVal sensor As IntPtr) As IntPtr
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSetup_SetAlignmentType(ByVal setup As IntPtr, ByVal type As GoAlignmentType) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSetup_SetAlignmentStationaryTarget(ByVal setup As IntPtr, ByVal target As GoAlignmentTarget) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSensor_Align(ByVal sensor As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSystem_ReceiveData(ByVal system As IntPtr, ByRef data As IntPtr, ByVal timeout As UInt64) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoDataSet_Count(ByVal dataset As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoDataSet_At(ByVal dataset As IntPtr, ByVal index As UInt32) As IntPtr
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoAlignMsg_Status(ByVal msg As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoSystem_Stop(ByVal sensor As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoDataMsg_Type(ByVal msg As IntPtr) As kStatus
    End Function
    <DllImport(Constants.GODLLPATH)> _
    Public Function GoDestroy(ByVal obj As IntPtr) As kStatus
    End Function
    <DllImport(Constants.KAPIDLLPATH)> _
    Public Function kIpAddress_Parse(ByVal addressPointer As IntPtr, ByVal text As String) As kStatus
    End Function

    Function Main() As Integer
        Dim status As kStatus
        Dim api As IntPtr = IntPtr.Zero
        Dim system As IntPtr = IntPtr.Zero
        Dim sensor As IntPtr = IntPtr.Zero
        Dim setup As IntPtr = IntPtr.Zero
        Dim dataset As IntPtr = IntPtr.Zero
        Dim alignMsg As IntPtr = IntPtr.Zero
        Dim addr As New address
        Dim addrPtr As IntPtr = IntPtr.Zero

        status = GoSdk_Construct(api)
        If status <> 1 Then
            Console.WriteLine("GoSdk_Construct Error:{0}", status)
            Return status
        End If

        status = GoSystem_Construct(system, IntPtr.Zero)
        If status <> 1 Then
            Console.WriteLine("GoSystem_Construct Error:{0}", status)
            Return status
        End If

        addrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(addr))
        Marshal.StructureToPtr(addr, addrPtr, False)

        status = kIpAddress_Parse(addrPtr, IP)
        If status <> 1 Then
            Console.WriteLine("kIpAddress_Parse Error:{0}", status)
            Return status
        End If

        status = GoSystem_FindSensorByIpAddress(system, addrPtr, sensor)
        If status <> 1 Then
            Console.WriteLine("GoSystem_FindSensorByIpAddress Error:{0}", status)
            Return status
        End If

        status = GoSensor_Connect(sensor)
        If status <> 1 Then
            Console.WriteLine("GoSensor_Connect Error:{0}", status)
            Return status
        End If

        status = GoSystem_EnableData(system, True)
        If status <> 1 Then
            Console.WriteLine("GoSystem_EnableData Error:{0}", status)
            Return status
        End If

        setup = GoSensor_Setup(sensor)
        If setup = IntPtr.Zero Then
            Console.WriteLine("GoSensor_Setup: Invalid Handle")
            Return status
        End If

        status = GoSetup_SetAlignmentType(setup, GoAlignmentType.GO_ALIGNMENT_TYPE_STATIONARY)
        If status <> 1 Then
            Console.WriteLine("GoSetup_SetAlignmentType Error:{0}", status)
            Return status
        End If

        status = GoSetup_SetAlignmentStationaryTarget(setup, GoAlignmentTarget.GO_ALIGNMENT_TARGET_NONE)
        If status <> 1 Then
            Console.WriteLine("GoSetup_SetAlignmentStationaryTarget Error:{0}", status)
            Return status
        End If

        status = GoSensor_Align(sensor)
        If status <> 1 Then
            Console.WriteLine("GoSensor_Align Error:{0}", status)
            Return status
        End If

        Console.WriteLine("Waiting for alignment calibration data to be collected...")

        status = GoSystem_ReceiveData(system, dataset, 30000000)

        If status = -993 Then
            Console.WriteLine("Failed to collect data for calibration within timeout limit...")
        ElseIf status <> 1 Then
            Console.WriteLine("Go2System_ReceiveData Error:{0}", status)
        Else
            ' each result can have multiple data items
            Dim itemCount = GoDataSet_Count(dataset)
            ' loop through all items in result message
            For i As Integer = 0 To itemCount - 1
                Dim dataItem = GoDataSet_At(dataset, i)
                ' if data item is of type 705 (GO2_TYPE_ALIGNMENT_DATA )
                If GoDataMsg_Type(dataItem) = GoDataMessageTypes.GO_DATA_MESSAGE_TYPE_ALIGNMENT Then
                    status = GoAlignMsg_Status(dataItem)
                    If status = 1 Then
                        Console.WriteLine("Alignment calibration successful!")
                    Else
                        Console.WriteLine("Alignment calibration failed.")
                    End If
                End If
            Next
            GoDestroy(dataset)
            Console.WriteLine(Environment.NewLine)
        End If

        status = GoSystem_Stop(system)
        If status <> 1 Then
            Console.WriteLine("GoSystem_Stop Error:{0}", status)
            Return status
        End If

        status = GoDestroy(system)
        If status <> 1 Then
            Console.WriteLine("GoDestroy Error:{0}", status)
            Return status
        End If

        status = GoDestroy(api)
        If status <> 1 Then
            Console.WriteLine("GoDestroy Error:{0}", status)
            Return status
        End If

        'wait for ENTER key
        Console.WriteLine("Press ENTER to continue")
        Do While Not Console.ReadKey(True).Key = ConsoleKey.Enter
            Thread.Sleep(100)
        Loop
        Return status
    End Function

End Module
