Search code examples
c#visual-studio-2013

USB relay DLL problems


I got USB relay which I need to program so that in specified times it would open for some time and then close. I tried to integrate DLL provided to me, but couldn't do it (or maybe I just did something wrong). Also tried to find some guide how to do this, also without success.

USB relay: songle srd-05vdc-sl-c

I am using VS 2013 and I am trying to make simple C# application. Also maybe there is something else wrong because HIDAPI GUI application does not show my relay as connected device. I am sitting on Windows 8 if that changes anything.


Solution

  • Since your DLL is an C++ or C library with exports, you can use platform invoke to call methods in the dll.

    Using the files you provided in the comments (mirror - 16.06.2015), here's what your wrapper could look like. There may be errors so please treat this like an example. I added XML comments based on the comments in the header file.

    Note that in order for this to work, you need to place usb_relay_device.dll in the same folder as your C# executable. The best way to do this is to add the file to your project and set "Copy to Output Directory" in VS's Solution Explorer to Copy Always or Copy if newer.

    Note: As noted in the comments, if the example throws an error about an unbalanced stack, add CallingConvention = CallingConvention.Cdecl to the DllImport attribute, or try another calling convention.

    using System;
    using System.Runtime.InteropServices;
    
    namespace UsbRelay
    {
        public static class UsbRelayDevice
        {
            /// <summary>
            /// Init the USB Relay Libary
            /// </summary>
            /// <returns>This function returns 0 on success and -1 on error.</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_init")]
            public static extern int Init();
    
            /// <summary>
            /// Finalize the USB Relay Libary.
            /// This function frees all of the static data associated with
            /// USB Relay Libary. It should be called at the end of execution to avoid
            /// memory leaks.
            /// </summary>
            /// <returns>This function returns 0 on success and -1 on error.</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_exit")]
            public static extern int Exit();
    
            /// <summary>
            /// Enumerate the USB Relay Devices.
            /// </summary>
            /// <returns></returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_enumerate")]
            public static extern UsbRelayDeviceInfo Enumerate();
    
            /// <summary>
            /// Free an enumeration Linked List
            /// </summary>
            /// <param name="deviceInfo"></param>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_free_enumerate")]
            public static extern void FreeEnumerate(UsbRelayDeviceInfo deviceInfo);
    
            /// <summary>
            /// Open device that serial number is serialNumber
            /// </summary>
            /// <param name="serialNumber"></param>
            /// <param name="stringLength"></param>
            /// <returns>This funcation returns a valid handle to the device on success or NULL on failure.</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_open_with_serial_number", CharSet = CharSet.Ansi)]
            public static extern int OpenWithSerialNumber([MarshalAs(UnmanagedType.LPStr)] string serialNumber, int stringLength);
    
            /// <summary>
            /// Open a usb relay device
            /// </summary>
            /// <param name="deviceInfo"></param>
            /// <returns>This funcation returns a valid handle to the device on success or NULL on failure.</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_open")]
            public static extern int Open(UsbRelayDeviceInfo deviceInfo);
    
            /// <summary>
            /// Close a usb relay device
            /// </summary>
            /// <param name="hHandle"></param>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_close")]
            public static extern void Close(int hHandle);
    
            /// <summary>
            /// open a relay channel on the USB-Relay-Device
            /// </summary>
            /// <param name="hHandle">Which usb relay device your want to operate</param>
            /// <param name="index">Which channel your want to open</param>
            /// <returns>0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_open_one_relay_channel")]
            public static extern int OpenOneRelayChannel(int hHandle, int index);
    
            /// <summary>
            /// open all relay channel on the USB-Relay-Device
            /// </summary>
            /// <param name="hHandle">which usb relay device your want to operate</param>
            /// <returns>0 -- success; 1 -- error</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_open_all_relay_channel")]
            public static extern int OpenAllRelayChannels(int hHandle);
    
            /// <summary>
            /// close a relay channel on the USB-Relay-Device
            /// </summary>
            /// <param name="hHandle">which usb relay device your want to operate</param>
            /// <param name="index">which channel your want to close</param>
            /// <returns>0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_close_one_relay_channel")]
            public static extern int CloseOneRelayChannel(int hHandle, int index);
    
            /// <summary>
            /// close all relay channel on the USB-Relay-Device
            /// </summary>
            /// <param name="hHandle">hich usb relay device your want to operate</param>
            /// <returns>0 -- success; 1 -- error</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_close_all_relay_channel")]
            public static extern int CloseAllRelayChannels(int hHandle);
    
            /// <summary>
            /// status bit: High --> Low 0000 0000 0000 0000 0000 0000 0000 0000, one bit indicate a relay status.
            /// the lowest bit 0 indicate relay one status, 1 -- means open status, 0 -- means closed status.
            /// bit 0/1/2/3/4/5/6/7/8 indicate relay 1/2/3/4/5/6/7/8 status
            /// </summary>
            /// <param name="hHandle"></param>
            /// <param name="status"></param>
            /// <returns>0 -- success; 1 -- error</returns>
            [DllImport("usb_relay_device.dll", EntryPoint = "usb_relay_device_get_status")]
            public static extern int GetStatus(int hHandle, ref int status);
        }
    
        /// <summary>
        /// USB relay board info structure
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack=8)]
        public class UsbRelayDeviceInfo
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string SerialNumber;
    
            [MarshalAs(UnmanagedType.LPStr)]
            public string DevicePath;
    
            public UsbRelayDeviceType Type;
    
            public UsbRelayDeviceInfo Next;
        }
    
        public enum UsbRelayDeviceType
        {
            OneChannel = 1,
            TwoChannel = 2,
            FourChannel = 4,
            EightChannel = 8
        }
    }
    

    To open the relay channel 1 in your device, you could do something like this:

    if (UsbRelayDevice.Init() != 0)
    {
        Console.WriteLine("Couldn't initialize!");
        return;
    }
    string serial = "serial number here";
    int deviceHandle = UsbRelayDevice.OpenWithSerialNumber(serial, serial.Length);
    int openResult = UsbRelayDevice.OpenOneRelayChannel(deviceHandle, 1);
    if (openResult == 1)
    {
        Console.WriteLine("Got error from OpenOneRelayChannel!");
        return;
    }
    else if (openResult == 2)
    {
        Console.WriteLine("Index is out of range on the usb relay device");
        return;
    }