]> git.itanic.dy.fi Git - rrdd/commitdiff
onewire_parser: Make sensor readin more robust on noisy 1-wire networks
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Wed, 20 Aug 2014 19:07:05 +0000 (22:07 +0300)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Fri, 22 Aug 2014 18:06:22 +0000 (21:06 +0300)
On noisy environment there may be transient read failures with some
1-wire sensors. The sensors might "come and go" and also read results
might fail with "85 degree results".

Try to work around the issue by retrying a sensor read with uncached
data. This helps in cases where there was a error during 1-wire scan
and some sensors were not detected. This also helps when sensor
responds but reading the result produces "85" degree result.

Reading should be significantly more reliable with this change.

Signed-off-by: Timo Kokkonen <timo.t.kokkonen@iki.fi>
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 */