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