In repsonse to the problem with "Belkin Regulator Pro dropping connection and halting" in ups-users, I've submitted the patch to help with the issue:
https://alioth.debian.org/tracker/index.php?func=detail&aid=312877&group_id=30602&atid=411544

I didn't have any reports of people's eyes bleeding from reading the code, and it's been doing the job quite nicely for me.

John
--- drivers/belkin.h.2571       2010-12-02 12:06:05.000000000 +0000
+++ drivers/belkin.h    2010-12-06 15:06:55.000000000 +0000
@@ -15,6 +15,12 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+   Author           : Marcus Müller
+   Created On       :
+   Last Modified By : John Bayly
+   Last Modified On : Monday December 06, 2010, 15:05 GMT
+
 */
 
 #include <sys/ioctl.h>
@@ -39,8 +45,8 @@
 #define POWER_CYCLE    "SDA"   /* shutdown, then restore */
 #define BUZZER "BUZ"
 #define BUZZER_ON "1"
-#define BUZZER_OFF0 "0" /* Switching the buzzer off can be either 0 or 2 */
-#define BUZZER_OFF2 "2" /* Seems to be used for F6c1400 */
+#define BUZZER_OFF0 "0"        /* Switching the buzzer off can be either 0 or 
2 */
+#define BUZZER_OFF2 "2"        /* Seems to be used for F6c1400 */
 #define TEST "TST"
 #define TEST_10SEC "3"
 #define TEST_DEEP "4"
@@ -51,6 +57,9 @@
 
 #define LOW_BAT                20
 
+/* the maximum allowed number of missed replies */
+#define MAXTRIES       3
+
 /* dangerous instant commands must be reconfirmed within a 12 second window */
 #define CONFIRM_DANGEROUS_COMMANDS 1
 #define MINCMDTIME     3
--- drivers/belkin.c.2571       2010-10-15 14:35:04.000000000 +0000
+++ drivers/belkin.c    2010-12-06 15:06:58.000000000 +0000
@@ -21,6 +21,11 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+   Author           : Marcus Müller
+   Created On       :
+   Last Modified By : John Bayly
+   Last Modified On : Monday December 06, 2010, 15:05 GMT
 */
 
 #include "main.h"
@@ -28,7 +33,7 @@
 #include "belkin.h"
 
 #define DRIVER_NAME    "Belkin Smart protocol driver"
-#define DRIVER_VERSION "0.23"
+#define DRIVER_VERSION "0.24"
 
 /* driver description structure */
 upsdrv_info_t upsdrv_info = {
@@ -39,8 +44,13 @@
        { NULL }
 };
 
+/** the number of replies that have been missed */
+static int retry = 0;
+
 static void send_belkin_command(char cmd, const char *subcmd, const char *data)
 {
+       upsdebugx(6, "Send Command: %s, %s", subcmd, data);
+       ser_flush_io(upsfd);
        ser_send(upsfd, "~00%c%03d%s%s", cmd, (int)strlen(data) + 3, subcmd, 
data);
 }
 
@@ -96,53 +106,76 @@
        return NULL;
 }
 
-static int do_status(void)
+static char *get_status()
 {
        char    temp[SMALLBUF], st[SMALLBUF];
        int     res;
+       const char      *status = NULL;
 
        send_belkin_command(STATUS,STAT_STATUS,"");
        res = get_belkin_reply(temp);
-       if (res == -1) {
-               dstate_datastale();
-               return 0;
-       }
-
-       status_init();
-
+       if (res < 1)
+               return NULL;
+       
        get_belkin_field(temp, st, sizeof(st), 6);
        if (*st == '1') {
-               status_set("OFF");
-
-       } else {        /* (OFF) and (OB | OL) are mutually exclusive */
+               status = "OFF";
 
+       } else if (*st == '0') {        /* (OFF) and (OB | OL) are mutually 
exclusive */
                get_belkin_field(temp, st, sizeof(st), 2);
                if (*st == '1') {
-                       status_set("OB");
+                       status = "OB";  /* on battery */
 
                        send_belkin_command(STATUS,STAT_BATTERY,"");
                        res = get_belkin_reply(temp);
 
-                       if (res == -1) {
-                               dstate_datastale();
-                               return 0;
+                       if (res < 1) {  /* no battery info, so no reliable 
status */
+                               status = NULL;
+
+                       } else {
+                               get_belkin_field(temp, st, sizeof(st), 10);
+                               res = atoi(st);
+                               get_belkin_field(temp, st, sizeof(st), 2);
+
+                               if (*st == '1' || res < LOW_BAT) 
+                                       status = "LB";  /* low battery */
                        }
 
-                       get_belkin_field(temp, st, sizeof(st), 10);
-                       res = atoi(st);
-                       get_belkin_field(temp, st, sizeof(st), 2);
+               } else if (*st == '0') {
+                       status = "OL";  /* on line */
 
-                       if (*st == '1' || res < LOW_BAT) 
-                               status_set("LB");       /* low battery */
                }
-               else
-                       status_set("OL");       /* on line */
        }
 
-       status_commit();
-       dstate_dataok();
+       return status;
+}
 
-       return 1;
+static int do_status(void)
+{
+       /* fetch the UPS status, or null if unavailable */
+       const char      *status = get_status();
+       
+       if (status) {
+               if (retry)      /* previous attempt had failed */
+                       upslogx(LOG_WARNING, "Communications with UPS 
re-established");
+
+               status_init();
+               status_set(status);
+               status_commit();
+               dstate_dataok();
+               retry = 0;
+               return 1;
+
+       } else {
+               if (retry < MAXTRIES) {
+                       upslogx(LOG_WARNING, "Communications with UPS lost: 
status read failed!");
+                       retry++;
+
+               } else {        /* too many retries */
+                       dstate_datastale();
+               }
+               return 0;
+       }
 }
 
 static int do_broken_rat(char *buf)
@@ -326,6 +359,14 @@
                        break;
 
        }
+
+       send_belkin_command(STATUS,STAT_STATUS, "");
+       res = get_belkin_reply(temp);
+       if (res == -1)
+               return;
+
+       get_belkin_field(temp, st, sizeof(st), 16);
+       dstate_setinfo("ups.beeper.status", "%s", (*st == '0' ? "disabled" : 
"enabled"));
 }
 
 static int get_belkin_reply(char *buf)
@@ -335,7 +376,7 @@
 
        usleep(25000);
 
-       /* pull first 7 bytes to get data length - like ~00S004 */
+       /* pull first 7 bytes to get data length - like ~00D004 */
        ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
 
        if (ret != 7) {
@@ -345,8 +386,13 @@
 
        tmp[7] = 0;
        cnt = atoi(tmp + 4);
+       upsdebugx(6, "Received: %s", tmp);
 
-       if ((cnt < 1) || (cnt > 255))
+       if (cnt == 0) { /* possible to have ~00R000, return empty response */
+               buf[0] = 0;
+               return 0;
+
+       } else if ((cnt < 1) || (cnt > 255))
                return -1;
 
        /* give it time to respond to us */
@@ -355,6 +401,7 @@
        ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 3, 0);
 
        buf[cnt] = 0;
+       upsdebugx(6, "Received: %s", buf);
 
        if (ret != cnt) {
                ser_comm_fail("Second read returned %d bytes, expected %d",
_______________________________________________
Nut-upsdev mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev

Reply via email to