From 8df79560c1047f4c15b150591a118ad53ebee6ce Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Wed, 20 Aug 2014 22:07:05 +0300 Subject: [PATCH] onewire_parser: Make sensor readin more robust on noisy 1-wire networks 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 --- onewire_parser.c | 67 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/onewire_parser.c b/onewire_parser.c index e440810..4a86ced 100644 --- a/onewire_parser.c +++ b/onewire_parser.c @@ -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 */ -- 2.44.0