'   Example Visual Studio VB code For controlling the IOM2 USB relay Module by interfacing To the IOM2.dll file. The IOM2.dll file 
'   will handle all of the serial communications with the module. 
'
'   Copy IOM2.dll into the project folder and add to the project via Add>Existing Item. In Properties for the dll, set Build Action
'   to None and Copy to Output Directory to Copy always.
'
'   The number of the virtual COM port created upon installation of the module must be known. That number must be either passed
'   to Start_IOM2 or selected via SelectPort_IOM2 in order to open the port and initiate communications.
'
'   Before terminating the program, Stop_IOM2 should be called to stop communications, close the COM port, and gracefully clean up
'   any resources created.
'
'   In between Start_IOM2 or SelectPort_IOM2 and Stop_IOM2, a variety of functions can be called including those to control the
'   relays or check the state of the inputs.
'
'   Copyright © 2024 BadgerWare, LLC. All rights reserved.
'   www.badgerware.net
'   www.usb-relay.com

Imports System.Runtime.InteropServices  ' Required for DllImport to be used

Public Class Form1
    ' Imports and prototypes for routines available in IOM2.dll
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub Start_IOM2(port As Integer)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function SelectPort_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetStatus_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput1_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput2_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput3_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput4_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput5_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput6_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput7_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetInput8_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelays_IOM2(R1 As Boolean, R2 As Boolean, R3 As Boolean, R4 As Boolean, R5 As Boolean, R6 As Boolean, R7 As Boolean, R8 As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay1_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay2_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay3_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay4_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay5_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay6_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay7_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub SetRelay8_IOM2(state As Boolean, Optional addr As Integer = 0)
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Function GetNumRelays_IOM2() As Integer
    End Function
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub Test_IOM2()
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub ShowDllVersion_IOM2()
    End Sub
    <DllImport("IOM2.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi)>
    Public Shared Sub Stop_IOM2()
    End Sub

    ' If the application knows the COM port number (e.g.can retrieve it from a file or the application provides its own selection of
    ' the port number), call Start_IOM2 with the known port number as the argument.
    Private Sub StartBtn_Click(sender As Object, e As EventArgs) Handles StartBtn.Click
        Start_IOM2(ComPortBox.SelectedIndex)    ' Opens the COM port and initiates communications
    End Sub

    ' As an alternative to Start_IOM2, SelectPort_IOM2 can be called. A window providing COM port selection will be displayed.
    Private Sub PortBtn_Click(sender As Object, e As EventArgs) Handles PortBtn.Click
        ComPortBox.SelectedIndex = SelectPort_IOM2()    ' Displays the selection window, opens the selected COM port, and initiates communications
    End Sub

    Private Sub GetNumRelaysBtn_Click(sender As Object, e As EventArgs) Handles GetNumRelaysBtn.Click
        GetNumRelaysBtn.Text = GetNumRelays_IOM2()  ' Queries the module for the number of relays available (0 if comms issue)
    End Sub

    Private Sub TestBtn_Click(sender As Object, e As EventArgs) Handles TestBtn.Click
        Test_IOM2() ' Displays a window providing an interface to allow the end user to manually test the hardware and external connections
    End Sub

    Private Sub ShowDllVersionBtn_Click(sender As Object, e As EventArgs) Handles ShowDllVersionBtn.Click
        ShowDllVersion_IOM2()   ' Displays a window showing the IOM2.dll version information
    End Sub

    ' On command call to Stop_IOM2 for demonstration purposes. In most cases, it's probably best to call it when the application is
    ' about to terminate.
    Private Sub StopBtn_Click(sender As Object, e As EventArgs) Handles StopBtn.Click
        Stop_IOM2() ' Stops communications, closes the COM port, and gracefully cleans up any resources created
    End Sub

    ' 250 msec timer to continuously check communications status and query the states of the inputs. If the inputs are not used, the
    ' states do not need to be queried. It's possible to just blindly turn the relays on and off without checking the communications
    ' status, but probably best to know if there is an issue.
    Private Sub UpdateTimer_Tick(sender As Object, e As EventArgs) Handles UpdateTimer.Tick
        Select Case GetStatus_IOM2()
            Case -1
                StatusLabel.Text = "IOM2 Status: Unknown"
            Case 0
                StatusLabel.Text = "IOM2 Status: Ok"
            Case 1
                StatusLabel.Text = "IOM2 Status: COM Port is off"
            Case 2
                StatusLabel.Text = "IOM2 Status: COM Port conflict"
            Case 3
                StatusLabel.Text = "IOM2 Status: No connection"
            Case 4
                StatusLabel.Text = "IOM2 Status: Parsing error"
        End Select

        ' Query the states of each of the inputs.
        Input1Label.Visible = GetInput1_IOM2()
        Input2Label.Visible = GetInput2_IOM2()
        Input3Label.Visible = GetInput3_IOM2()
        Input4Label.Visible = GetInput4_IOM2()
        Input5Label.Visible = GetInput5_IOM2()
        Input6Label.Visible = GetInput6_IOM2()
        Input7Label.Visible = GetInput7_IOM2()
        Input8Label.Visible = GetInput8_IOM2()
    End Sub

    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
        Stop_IOM2() ' Stops communications, closes the COM port, and gracefully cleans up any resources created
    End Sub

    ' Set the states of each of the relays with a single command.
    Private Sub SetRelaysBtn_Click(sender As Object, e As EventArgs) Handles SetRelaysBtn.Click
        SetRelays_IOM2(Relay1Box.Checked, Relay2Box.Checked, Relay3Box.Checked, Relay4Box.Checked, Relay5Box.Checked, Relay6Box.Checked, Relay7Box.Checked, Relay8Box.Checked)
    End Sub

    Private Sub Relay1OnBtn_Click(sender As Object, e As EventArgs) Handles Relay1OnBtn.Click
        SetRelay1_IOM2(True)    ' Turn relay 1 on
    End Sub

    Private Sub Relay1OffBtn_Click(sender As Object, e As EventArgs) Handles Relay1OffBtn.Click
        SetRelay1_IOM2(False)    ' Turn relay 1 off
    End Sub

    Private Sub Relay2OnBtn_Click(sender As Object, e As EventArgs) Handles Relay2OnBtn.Click
        SetRelay2_IOM2(True)    ' Turn relay 2 on
    End Sub

    Private Sub Relay2OffBtn_Click(sender As Object, e As EventArgs) Handles Relay2OffBtn.Click
        SetRelay2_IOM2(False)    ' Turn relay 2 off
    End Sub

    Private Sub Relay3OnBtn_Click(sender As Object, e As EventArgs) Handles Relay3OnBtn.Click
        SetRelay3_IOM2(True)    ' Turn relay 3 on
    End Sub

    Private Sub Relay3OffBtn_Click(sender As Object, e As EventArgs) Handles Relay3OffBtn.Click
        SetRelay3_IOM2(False)    ' Turn relay 3 off
    End Sub

    Private Sub Relay4OnBtn_Click(sender As Object, e As EventArgs) Handles Relay4OnBtn.Click
        SetRelay4_IOM2(True)    ' Turn relay 4 on
    End Sub

    Private Sub Relay4OffBtn_Click(sender As Object, e As EventArgs) Handles Relay4OffBtn.Click
        SetRelay4_IOM2(False)    ' Turn relay 4 off
    End Sub

    Private Sub Relay5OnBtn_Click(sender As Object, e As EventArgs) Handles Relay5OnBtn.Click
        SetRelay5_IOM2(True)    ' Turn relay 5 on
    End Sub

    Private Sub Relay5OffBtn_Click(sender As Object, e As EventArgs) Handles Relay5OffBtn.Click
        SetRelay5_IOM2(False)    ' Turn relay 5 off
    End Sub

    Private Sub Relay6OnBtn_Click(sender As Object, e As EventArgs) Handles Relay6OnBtn.Click
        SetRelay6_IOM2(True)    ' Turn relay 6 on
    End Sub

    Private Sub Relay6OffBtn_Click(sender As Object, e As EventArgs) Handles Relay6OffBtn.Click
        SetRelay6_IOM2(False)    ' Turn relay 6 off
    End Sub

    Private Sub Relay7OnBtn_Click(sender As Object, e As EventArgs) Handles Relay7OnBtn.Click
        SetRelay7_IOM2(True)    ' Turn relay 7 on
    End Sub

    Private Sub Relay7OffBtn_Click(sender As Object, e As EventArgs) Handles Relay7OffBtn.Click
        SetRelay7_IOM2(False)    ' Turn relay 7 on
    End Sub

    Private Sub Relay8OnBtn_Click(sender As Object, e As EventArgs) Handles Relay8OnBtn.Click
        SetRelay8_IOM2(True)    ' Turn relay 8 on
    End Sub

    Private Sub Relay8OffBtn_Click(sender As Object, e As EventArgs) Handles Relay8OffBtn.Click
        SetRelay8_IOM2(False)    ' Turn relay 8 off
    End Sub
End Class
