From 17a1358ccbc3709a895b5d997e2bd8c859ac759e Mon Sep 17 00:00:00 2001
From: Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
Date: Thu, 22 Nov 2018 18:53:03 +0100
Subject: [PATCH] tests: add test application for sds011 driver

---
 tests/driver_sds011/Makefile |   6 +
 tests/driver_sds011/main.c   | 236 +++++++++++++++++++++++++++++++++++
 2 files changed, 242 insertions(+)
 create mode 100644 tests/driver_sds011/Makefile
 create mode 100644 tests/driver_sds011/main.c

diff --git a/tests/driver_sds011/Makefile b/tests/driver_sds011/Makefile
new file mode 100644
index 0000000000..03a1d7827e
--- /dev/null
+++ b/tests/driver_sds011/Makefile
@@ -0,0 +1,6 @@
+include ../Makefile.tests_common
+
+USEMODULE += sds011
+USEMODULE += xtimer
+
+include $(RIOTBASE)/Makefile.include
diff --git a/tests/driver_sds011/main.c b/tests/driver_sds011/main.c
new file mode 100644
index 0000000000..7d5b83c123
--- /dev/null
+++ b/tests/driver_sds011/main.c
@@ -0,0 +1,236 @@
+/**
+ * Copyright (C) 2018 HAW-Hamburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     tests
+ * @{
+ *
+ * @file
+ * @brief       Test application for the SDS011 Laser Dust Sensor driver
+ *
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
+ *
+ * @}
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "xtimer.h"
+
+#include "sds011.h"
+#include "sds011_params.h"
+#include "msg.h"
+#include "thread.h"
+
+#define ACTIVE_REPORTING_TEST_CNT                (20U)
+#define PUT_TO_QUERY_MODE_RETRIES                (3U)
+#define PUT_TO_QUERY_MODE_RETRY_TIMEOUT_MS       (100U)
+#define MANUAL_QUERY_CNT                         (10U)
+#define WORKING_PERIOD                           (0U)
+
+/**
+ * @brief   Allocate the device descriptor
+ */
+static sds011_t dev;
+
+static char* _rmode_str(sds011_reporting_mode_t rmode)
+{
+    switch (rmode) {
+        case SDS011_RMODE_ACTIVE:
+            return "ACTIVE";
+        case SDS011_RMODE_QUERY:
+            return "QUERY";
+        default:
+            return "INVALID";
+    }
+}
+
+static char* _wmode_str(sds011_working_mode_t wmode)
+{
+    switch (wmode) {
+        case SDS011_WMODE_WORK:
+            return "WORK";
+        case SDS011_WMODE_SLEEP:
+            return "SLEEP";
+        default:
+            return "INVALID";
+    }
+}
+
+static void _print_measurement(sds011_data_t *data)
+{
+    uint16_t pm10_ug_int = data->pm_10 / 10;
+    uint16_t pm10_ug_dec = data->pm_10 - 10 * pm10_ug_int;
+    uint16_t pm2_5_ug_int = data->pm_2_5 / 10;
+    uint16_t pm2_5_ug_dec = data->pm_2_5 - 10 * pm2_5_ug_int;
+    printf("==> PM2.5: %d.%0d ug/m^3 | PM10: %d.%0d ug/m^3\n",
+           pm2_5_ug_int, pm2_5_ug_dec, pm10_ug_int, pm10_ug_dec);
+}
+
+void measure_cb(sds011_data_t *data, void *ctx)
+{
+    msg_t msg = { .content.value = (((uint32_t)data->pm_10) << 16 | data->pm_2_5) };
+    kernel_pid_t target_pid = (int)ctx;
+    msg_send(&msg, target_pid);
+}
+
+int main(void)
+{
+    unsigned retry_cnt = 0;
+    uint8_t year;
+    uint8_t month;
+    uint8_t day;
+    sds011_reporting_mode_t rmode;
+    sds011_working_mode_t wmode;
+    uint8_t minutes;
+    sds011_data_t data;
+
+    puts("SDS011 test application");
+
+    /* initialize the driver */
+    if (sds011_init(&dev, &sds011_params[0]) == SDS011_OK) {
+        puts("init [OK]");
+    }
+    else {
+        puts("initalization [ERROR]");
+        return -1;
+    }
+
+    printf("setting reporting mode to '%s'...\n", _rmode_str(SDS011_RMODE_QUERY));
+
+    /* set the sensor to query mode to disable active reporting messages
+       -> to work correctly, this step may need to be repeated if the automatic
+          output is incoming while the reply is expected */
+    while (sds011_set_reporting_mode(&dev, SDS011_RMODE_QUERY) != SDS011_OK) {
+        if (retry_cnt++ >= PUT_TO_QUERY_MODE_RETRIES) {
+            puts("[ERROR]");
+            return -1;
+        }
+        xtimer_usleep(PUT_TO_QUERY_MODE_RETRY_TIMEOUT_MS * 1000);
+        puts("[RETRY]");
+    }
+
+    puts("[OK]");
+    puts("getting reporting mode from device...");
+
+    if (sds011_get_reporting_mode(&dev, &rmode) == SDS011_OK) {
+        printf("[OK] => mode: %s\n", _rmode_str(rmode));
+        if (rmode != SDS011_RMODE_QUERY) {
+            puts("mismatch! [ERROR]");
+            return -1;
+        }
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    puts("getting firmware version...");
+
+    if (sds011_get_fw_version(&dev, &year, &month, &day) == SDS011_OK) {
+        printf("[OK] => %d.%d.%d\n", year, month, day);
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    printf("setting working mode to '%s'...\n", _wmode_str(SDS011_WMODE_WORK));
+
+    if (sds011_set_working_mode(&dev, SDS011_WMODE_WORK) == SDS011_OK) {
+        puts("[OK]");
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    puts("getting working mode from device...");
+
+    if (sds011_get_working_mode(&dev, &wmode) == SDS011_OK) {
+        printf("[OK] => mode: %s\n", _wmode_str(wmode));
+        if (wmode != SDS011_WMODE_WORK) {
+            puts("mismatch! [ERROR]");
+            return -1;
+        }
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    printf("setting working period to %u...\n", WORKING_PERIOD);
+
+    if (sds011_set_working_period(&dev, WORKING_PERIOD) == SDS011_OK) {
+        puts("[OK]");
+    }
+    else {
+        puts("[ERROR]");
+        return 1;
+    }
+
+    if (sds011_get_working_period(&dev, &minutes) == SDS011_OK) {
+        printf("[OK] => working period: %u\n", minutes);
+        if (minutes != WORKING_PERIOD) {
+            puts("mismatch! [ERROR]");
+            return -1;
+        }
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    for (unsigned i = 0; i < MANUAL_QUERY_CNT; i++) {
+        if (sds011_read(&dev, &data) == SDS011_OK) {
+            printf("manual query %2u/%u [OK]: ", i + 1, MANUAL_QUERY_CNT);
+            _print_measurement(&data);
+        }
+    }
+
+    sds011_register_callback(&dev, measure_cb, (void*)(int)thread_getpid());
+
+    printf("switching to active reporting mode for %u measurements...\n",
+            ACTIVE_REPORTING_TEST_CNT);
+
+    if (sds011_set_reporting_mode(&dev, SDS011_RMODE_ACTIVE) == SDS011_OK) {
+        puts("[OK]");
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    /* wait a little bit so the callback gets executed a few times */
+    msg_t msg;
+    for(unsigned msg_cnt = 0; msg_cnt < ACTIVE_REPORTING_TEST_CNT; msg_cnt++){
+        msg_receive(&msg);
+        sds011_data_t data;
+        data.pm_10 = msg.content.value >> 16;
+        data.pm_2_5 = msg.content.value & 0xFFFF;
+        printf("msg from callback: ");
+        _print_measurement(&data);
+    }
+
+    /* unregister callback */
+    sds011_register_callback(&dev, NULL, NULL);
+
+    puts("switching to sleep mode...");
+
+    if (sds011_set_working_mode(&dev, SDS011_WMODE_SLEEP) == SDS011_OK) {
+        puts("[OK]");
+    }
+    else {
+        puts("[ERROR]");
+        return -1;
+    }
+
+    puts("[SUCCESS]");
+    return 0;
+}
-- 
GitLab