]> git.itanic.dy.fi Git - rrdd/blobdiff - onewire_parser.c
onewire_parser: Make sensor readin more robust on noisy 1-wire networks
[rrdd] / onewire_parser.c
index e440810743d3704471537f71b7a942a8f580b8a2..4a86ced9bdbc470410d1d850e2316ffcbd429422 100644 (file)
@@ -46,6 +46,33 @@ static int parse_opts(const char *str, char *ow_path, size_t pathlen, double *of
        return 0;
 }
 
+static int make_uncached(char *path, size_t len)
+{
+       char p1[32], p2[32], *p = path;
+
+       if (strstr(path, "/uncached/"))
+               return 0;
+
+       /*
+        * Naively assume the "uncached" string can be put after the
+        * first slash
+        */
+       while (*p && *p != '/')
+               p++;
+
+       if (!*p)
+               return -1;
+
+       *p = 0;
+       p++;
+
+       strncpy(p1, path, sizeof(p1));
+       strncpy(p2, p, sizeof(p2));
+       snprintf(path, len, "%s/uncached/%s", p1, p2);
+
+       return 0;
+}
+
 static int onewire_parser(char *rrd_data, const char **parser_data)
 {
        OWNET_HANDLE h;
@@ -76,6 +103,7 @@ static int onewire_parser(char *rrd_data, const char **parser_data)
                double offset = 0, data;
                char *endptr;
                char ow_path[1024];
+               int retries = 0;
 
                if (!strcmp("U", parser_data[i])) {
 undefined:
@@ -87,12 +115,39 @@ undefined:
 
                parse_opts(parser_data[i], ow_path, sizeof(ow_path), &offset);
 
-               pr_info("Reading data for entry %s with offset of %.2f\n",
-                       ow_path, offset);
-               ret = OWNET_read(h, ow_path, &tmp);
-               if (ret < 0) {
-                       pr_err("Failed to read entry %s\n", parser_data[i]);
-                       goto undefined;
+               while (1) {
+                       int fail, i;
+                       char *tmp2;
+
+                       pr_info("Reading data for entry %s with offset of %.2f\n",
+                               ow_path, offset);
+                       ret = OWNET_read(h, ow_path, &tmp);
+
+                       /* Skip leading white space */
+                       tmp2 = tmp;
+                       for (i = 0; i < ret && *tmp2 == ' '; i++)
+                               tmp2++;
+
+                       fail = !strncmp(tmp2, "85", 2);
+
+                       /*
+                        * In case of failure, retry with uncached
+                        * data. This is likely to help as it forces a
+                        * retry even if the sensor is missing from
+                        * the cache. We thread "85" also as a failure
+                        * above, as temp sensors some times report 85
+                        * under faulty conditions.
+                        */
+                       if (ret > 0 && !fail)
+                               break;
+
+                       ret = make_uncached(ow_path, sizeof(ow_path));
+                       if (retries >= 10 || ret < 0) {
+                               pr_err("Failed to read entry %s: %m\n",
+                                       parser_data[i]);
+                               goto undefined;
+                       }
+                       retries++;
                }
 
                /* The data from OWNET_read appears to not be NULL terminated */