Added support for 1, 4-relay device (still only one)
authorpavel <pavel@aaa>
Wed, 19 Nov 2014 17:36:13 +0000 (19:36 +0200)
committerpavel <pavel@aaa>
Wed, 19 Nov 2014 17:36:13 +0000 (19:36 +0200)
commandline/README-hidusb-relay-cmd.txt
commandline/usbrelay-cmd.c
doc/hidrelay.md

index e8115b76bbcca7f621f19b6bea0072a88d8daa5e..dfe6e665e00d530c6a8ac7ec3bed6de0e8393ed5 100644 (file)
@@ -1,7 +1,7 @@
 Command line utility for Chinese USB HID relays
 (USB 1.1 HID devices, VEN=5824 (0x16c0) DEV=1503 (0x05DF), based on the V-USB project)
 
-Rev. 1.0 (16-apr-2014)
+Rev. 1.1 (18-Nov-2014)
 
 Usage:
   usbrelay-cmd ON|OFF <num>   -- turn the relay ON or OFF
@@ -15,7 +15,7 @@ The ON state is when the red LED is on, and the Normally Open contacts are conne
 
 Note: In the original s/w readme, "Open" means ON, "Close" means OFF.
   
-Currently tested only with the 2-relay device.
+Currently tested with 1 and 2-relay devices.
 Finds the FIRST AVAILABLE RELAY device! Does not address by the "unique ID" yet!
 
 SOURCE based on a V-USB HID example.
@@ -41,10 +41,11 @@ For Linux (PC, x86):
 
 Other TODO's
 ============
-TODO: support multiple devices, support one-relay and other existing variants
-  usbrelay-cmd -SN=XXXXX ON|OFF <num>
-  usbrelay-cmd -SN=XXXXX  STATE       
-    or -s XXXXX or --SN or -ID ...
+TODO: support multiple devices, support other existing variants
+  usbrelay-cmd -ID=XXXXX ON|OFF <num>
+  usbrelay-cmd -ID=XXXXX  STATE       
+    or -s XXXXX or --SN 
+    -ID=* --ANY any one?
     
  *** Check that these devices indeed have unique IDs!
   The orig. h file mentions  function:   usb_relay_device_set_serial(int hHandle, char serial[5]);
@@ -66,5 +67,5 @@ Creation Date: 2008-04-11
 ~~
 The relay device ID - from HID attributes:
 vendorName = "www.dcttech.com" -> this site does not exist (squatted)
-productName = "USBRelay2"
+productName = "USBRelayN" where N=1|2|4
 
index f90b9c065e0361b522f7897b1a30db6195d5d7a8..bd7f4cc494952aa185c07d6b113a81a132360f56 100644 (file)
@@ -1,11 +1,9 @@
 // Chinese USB/HID relay command line tool:
 //
-// pa01 15-Apr-2014
+// pa02 19-Nov-2014 supports 1,2,4 - relay devices
 // Currently finds the 1st matching device by ven,dev, product name string.
-// Two channel devices only!
 // TODO:
-// - Enum all matching devices, select one by ID
-// - Determine the relay model (1 or 2 or more) by product string? 
+// - Support multiple devices, select one by ID!
 // Build for Windows: using VC++ 2008 and WDK7.1
 //~~~~~~~~~~~~~~~~~~~~~~~~
 
  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
  */
 
-#define A_VER_STR "r0.2 (2 ch. only)"
+#define A_VER_STR "r1.1x (1 device only)"
 
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include "hidusb-tool.h"
 
-#define USB_CFG_VENDOR_NAME     "www.dcttech.com"
-#define USB_CFG_DEVICE_NAME     "USBRelay2"  // can be relay1... relay8?
+#define USB_RELAY_VENDOR_NAME     "www.dcttech.com"
+#define USB_RELAY1_NAME           "USBRelay1"  // 1 relay
+#define USB_RELAY2_NAME           "USBRelay2"  // 2 relays
+#define USB_RELAY4_NAME           "USBRelay4"  // 4 relays
 
 
 static int g_max_relay_num = 0;
 
-static int rel_read_status(USBDEVHANDLE dev, void *raw_data);
+static int rel_read_status_raw(USBDEVHANDLE dev, void *raw_data);
 
 /* ------------------------------------------------------------------------- */
 
@@ -36,35 +36,53 @@ static const char *usbErrorMessage(int errCode)
 {
     static char buffer[80];
 
-    switch(errCode){
+    switch (errCode) {
         case USBOPEN_ERR_ACCESS:      return "Access to device denied";
         case USBOPEN_ERR_NOTFOUND:    return "The specified device was not found";
         case USBOPEN_ERR_IO:          return "Communication error with device";
-        default:
-            snprintf(buffer, sizeof(buffer), "Unknown USB error %d", errCode);
-            return buffer;
     }
-    return NULL;    /* not reached */
+
+    snprintf(buffer, sizeof(buffer), "Unknown USB error %d", errCode);
+    return buffer;
 }
 
 static USBDEVHANDLE openDevice(void)
 {
     USBDEVHANDLE    dev = 0;
-    char            vendorName[]  = USB_CFG_VENDOR_NAME, 
-                    productName[] = USB_CFG_DEVICE_NAME; 
+    char            vendorName[]  = USB_RELAY_VENDOR_NAME, 
+                    productName[] = USB_RELAY1_NAME; 
     int             vid = USB_CFG_VENDOR_ID;
     int             pid = USB_CFG_DEVICE_ID;
     int             err;
+    int num = 0;
 
     // TODO: enumerate all instances, then filter  by unique ID
-    if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) != 0){
-        fprintf(stderr, "error finding %s: %s\n", productName, usbErrorMessage(err));
-        return NULL;
+    //$$$ find any one device
+    strcpy(productName, USB_RELAY2_NAME);
+    if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+      num = 2;
+      goto check1;
+    }
+
+    strcpy(productName, USB_RELAY1_NAME);
+    if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+      num = 1;
+      goto check1;
+    }
+
+    strcpy(productName, USB_RELAY4_NAME);
+    if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) == 0) {
+      num = 4;
+      goto check1;
     }
 
+    fprintf(stderr, "error finding USB relay: %s\n", usbErrorMessage(err));
+    return NULL;
+
+    check1:
     { /* Check the unique ID: 5 bytes at offs 0 */
         char buffer[16];
-               err = rel_read_status(dev, buffer);
+        err = rel_read_status_raw(dev, buffer);
         if( err < 0 ){
             fprintf(stderr, "error reading report 0: %s\n", usbErrorMessage(err));
             usbhidCloseDevice(dev);
@@ -87,7 +105,7 @@ static USBDEVHANDLE openDevice(void)
             }
             
             DEBUG_PRINT(("Device %s found: ID=[%5s]\n", USB_CFG_DEVICE_NAME, &buffer[1]));
-            g_max_relay_num = 2; /* hardcoded for "USBRelay2" */
+            g_max_relay_num = num;
         }
     }
 
@@ -122,7 +140,7 @@ static void usage(char *myName)
 {
     char *p = strrchr(myName, '\\'); /* windows */
     if (p) myName = p + 1;
-    p = strrchr(myName, '/'); /* whatever */
+    else p = strrchr(myName, '/'); /* whatever */
     if (p) myName = p + 1;
 
     fprintf(stderr, "USBHID relay utility, " A_VER_STR "\n");
@@ -135,7 +153,7 @@ static void usage(char *myName)
 
 // Read state of all relays
 // @return bit mask of all relays (R1->bit 0, R2->bit 1 ...) or -1 on error
-static int rel_read_status(USBDEVHANDLE dev, void *raw_data)
+static int rel_read_status_raw(USBDEVHANDLE dev, void *raw_data)
 {
     char buffer[10];
     int err;
@@ -155,7 +173,7 @@ static int rel_read_status(USBDEVHANDLE dev, void *raw_data)
     }
 
     if (raw_data) {
-        /* REVISE! copy raw report data */
+        /* copy raw report data */
         memcpy( raw_data, buffer, sizeof(buffer) );
     }
 
@@ -195,7 +213,7 @@ static int rel_onoff( USBDEVHANDLE dev, int is_on, char const *numstr )
     }
     
     // Read back & verify
-    err = rel_read_status(dev, NULL);
+    err = rel_read_status_raw(dev, NULL);
     if ( err >= 0 ) {
         err = (err >> (unsigned)(relaynum -1)) & 1;
         err ^= !!is_on;
@@ -210,9 +228,45 @@ static int rel_onoff( USBDEVHANDLE dev, int is_on, char const *numstr )
 }
 
 
+static int show_status(USBDEVHANDLE dev)
+{
+    int err;
+    char buffer[10];
+       static const char* on_off[] = {"OFF","ON"};
+
+#define onoff(n) on_off[!!(err & (1U << n))]
+
+    err = rel_read_status_raw(dev, buffer);
+    if ( err < 0 ){
+        fprintf(stderr, "error reading data: %s\n", usbErrorMessage(err));
+        err = 1;
+    } else {
+        //hexdump(buffer + 1, len - 1);
+        switch (g_max_relay_num) {
+            case 1:
+                printf("Board ID=[%5.5s] State: R1=%s\n", &buffer[1], onoff(0) );
+                               break;
+            case 2:
+                printf("Board ID=[%5.5s] State: R1=%s R2=%s\n",
+                                       &buffer[1],     onoff(0), onoff(1) );
+                               break;
+            case 4:
+                printf("Board ID=[%5.5s] State: R1=%s R3=%s R1=%s R4=%s\n",
+                                       &buffer[1],     onoff(0), onoff(1), onoff(2), onoff(3) );
+                               break;
+            default:
+                               printf("Board ID=[%5.5s] State: %2.2X (hex)\n", &buffer[1], (unsigned char)err );
+                               break;
+        }
+        err = 0;
+    }
+    return err;
+#undef onoff
+}
+
 int main(int argc, char **argv)
 {
-    USBDEVHANDLE dev;
+    USBDEVHANDLE dev = 0;
     int         err;
     char const *arg1 = (argc >= 2) ? argv[1] : NULL;
     char const *arg2 = (argc >= 3) ? argv[2] : NULL;
@@ -226,20 +280,12 @@ int main(int argc, char **argv)
     if ( !dev )
         exit(1);
 
-//    if ( strcasecmp(arg1, "state") == 0 ){
-       if ( strncasecmp(arg1, "stat", 4) == 0 ){
-        char buffer[10];
-        err = rel_read_status(dev, buffer);
-        if ( err < 0 ){
-            fprintf(stderr, "error reading data: %s\n", usbErrorMessage(err));
-            err = 1;
-        } else {
-            //hexdump(buffer + 1, len - 1);
-            printf("State: R1=%d R2=%d Board ID=[%5.5s]\n", !!(err & 0x1), !!(err & 0x2), &buffer[1] );
-        }
-    }else if( strcasecmp(arg1, "on" ) == 0){
+    if ( strncasecmp(arg1, "stat", 4) == 0 ) { // stat|state|status
+        err = show_status(dev);
+               // TODO enumerate all devices
+    }else if( strcasecmp(arg1, "on" ) == 0) {
         err = rel_onoff(dev, 1, arg2);
-    }else if( strcasecmp(arg1, "off" ) == 0){
+    }else if( strcasecmp(arg1, "off" ) == 0) {
         err = rel_onoff(dev, 0, arg2);
     }else {
         usage(argv[0]);
index 3cf9d92baa2d21ab3bc93de090d6c9746cadb2fe..7e819f499a528014a2a72b9ea8e3c5731a8e84f1 100644 (file)
@@ -12,7 +12,5 @@ Two USB HID relays are on eBay
 - Each relay channel has Normally Open and Normally Closed contact. The status LED lighs when the Normally Open contacts get closed. We'll name this state "**ON**", and the "normal" state - "**OFF**".
 - The USB interface is low-speed (USB 1.1) HID, based on [V-USB](http://www.obdev.at/products/vusb/) software USB emulation library.
 - The USB device ID is VEN=16C0 DEV=05DF. This is the shared ID for V-USB HID class devices. The V-USB documentation describes how to detect the real vendor and product IDs for such devices.
-- For the 2-channel boards, the vendor ID is "www.dcttech.com" and product ID is "USBRelay2".
+- For 1 and 2-channel boards, the vendor ID is "www.dcttech.com" and product IDs are "USBRelay1", "USBRelay2".
 - Each board has an unique 5-character ID string in its HID descriptor (not to be confused with the standard USB "serial number"). We don't know whether these IDs are really unique, at least, on all our devices they are different.
-
-