From 930257e263aa030374b5e1c1682806280a53fe2d Mon Sep 17 00:00:00 2001 From: Kirill Isakov Date: Sun, 22 Nov 2020 22:41:12 +0600 Subject: [PATCH] Less copypasta in PM measurement calculation --- firmware/main/commands.cc | 6 ++-- firmware/main/dallas.cc | 20 +++++------ firmware/main/measurement.cc | 34 ------------------ firmware/main/measurement.hh | 26 ++------------ firmware/main/pm.hh | 67 ++++++++++++++++++++++++++++++++++++ firmware/main/pms.cc | 32 +++++++---------- firmware/main/pms.hh | 37 ++++---------------- 7 files changed, 101 insertions(+), 121 deletions(-) create mode 100644 firmware/main/pm.hh diff --git a/firmware/main/commands.cc b/firmware/main/commands.cc index a8906af..fb83571 100644 --- a/firmware/main/commands.cc +++ b/firmware/main/commands.cc @@ -82,7 +82,7 @@ static bool handleUnknown(mqtt::Client &client, const mqtt::Message &msg) { } static bool handleMessage(mqtt::Client &client, const mqtt::Message &msg) { - std::vector tokens; + CommandArgs tokens; const auto end = msg.data.cend(); for (auto begin = msg.data.cbegin(); begin != end;) { @@ -94,11 +94,11 @@ static bool handleMessage(mqtt::Client &client, const mqtt::Message &msg) { break; } } - begin = std::find_if(nextSpace, end, [](char c) { return !isspace(c); }); + begin = std::find_if(nextSpace, end, isgraph); } if (tokens.empty()) { - client.send(msg.topic, "no command specified"); + client.send(msg.respTopic, "no command specified"); return false; } diff --git a/firmware/main/dallas.cc b/firmware/main/dallas.cc index 275e498..bcb53bc 100644 --- a/firmware/main/dallas.cc +++ b/firmware/main/dallas.cc @@ -1,10 +1,8 @@ #include "dallas.hh" #include "common.hh" +#include "settings.hh" #include "time.hh" -// delay between two temperature measurements -static const int delayTemp = secToTicks(CONFIG_TEMPERATURE_PERIOD_SECONDS); - namespace ds { static std::unique_ptr findSensor(const OneWireBus &owb) { @@ -44,25 +42,24 @@ static std::unique_ptr findSensor(const OneWireBus &owb) { } void TempSensor::runMeasurements(const DS18B20_Info &device) { - int errCount = 0; Measurement ms{.type = MeasurementType::TEMPERATURE, .sensor = name}; TickType_t lastWakeTime = xTaskGetTickCount(); - while (errCount < 4) { + for (int errCount = 0; errCount < 4;) { const DS18B20_ERROR err = ds18b20_convert_and_read_temp(&device, &ms.temp); - if (err != DS18B20_OK) { - ++errCount; - ESP_LOGW(logTag, "measurement failed in %s, err %d", name, err); - } else { + if (err == DS18B20_OK) { errCount = 0; ms.time = getTimestamp(); if (!queue->putRetrying(ms)) { ESP_LOGE(logTag, "could not put temp measurement into queue"); } + } else { + ++errCount; + ESP_LOGW(logTag, "measurement failed in %s, err 0x%x", name, err); } - vTaskDelayUntil(&lastWakeTime, delayTemp); + vTaskDelayUntil(&lastWakeTime, appSettings.period.temp); } } @@ -71,9 +68,10 @@ void TempSensor::runMeasurements(const DS18B20_Info &device) { ESP_LOGI(logTag, "starting temp collection task for %s", sensor.name); - for (owb_rmt_driver_info driver_info;;) { + while (true) { vTaskDelay(secToTicks(2)); + owb_rmt_driver_info driver_info{}; std::unique_ptr owb{ owb_rmt_initialize(&driver_info, sensor.pin, sensor.txChan, sensor.rxChan), diff --git a/firmware/main/measurement.cc b/firmware/main/measurement.cc index 3311244..bc2f1a5 100644 --- a/firmware/main/measurement.cc +++ b/firmware/main/measurement.cc @@ -11,40 +11,6 @@ void Measurement::fixTime() { } } -void Measurement::set(const pms::Response &res) { - pm.atm.pm1Mcg = res.pm1McgAtm; - pm.atm.pm2Mcg = res.pm2McgAtm; - pm.atm.pm10Mcg = res.pm10McgAtm; - - pm.std.pm1Mcg = res.pm1McgStd; - pm.std.pm2Mcg = res.pm2McgStd; - pm.std.pm10Mcg = res.pm10McgStd; - - pm.cnt.pm03Count = res.pm03Count; - pm.cnt.pm05Count = res.pm05Count; - pm.cnt.pm1Count = res.pm1Count; - pm.cnt.pm2Count = res.pm2Count; - pm.cnt.pm5Count = res.pm5Count; - pm.cnt.pm10Count = res.pm10Count; -} - -void Measurement::set(const pms::ResponseSum &sum) { - pm.atm.pm1Mcg = sum.atm.pm1Mcg / sum.count; - pm.atm.pm2Mcg = sum.atm.pm2Mcg / sum.count; - pm.atm.pm10Mcg = sum.atm.pm10Mcg / sum.count; - - pm.std.pm1Mcg = sum.std.pm1Mcg / sum.count; - pm.std.pm2Mcg = sum.std.pm2Mcg / sum.count; - pm.std.pm10Mcg = sum.std.pm10Mcg / sum.count; - - pm.cnt.pm03Count = sum.cnt.pm03Count / sum.count; - pm.cnt.pm05Count = sum.cnt.pm05Count / sum.count; - pm.cnt.pm1Count = sum.cnt.pm1Count / sum.count; - pm.cnt.pm2Count = sum.cnt.pm2Count / sum.count; - pm.cnt.pm5Count = sum.cnt.pm5Count / sum.count; - pm.cnt.pm10Count = sum.cnt.pm10Count / sum.count; -} - const char *Measurement::getType() const { switch (type) { case MeasurementType::TEMPERATURE: diff --git a/firmware/main/measurement.hh b/firmware/main/measurement.hh index fb9beae..03811e0 100644 --- a/firmware/main/measurement.hh +++ b/firmware/main/measurement.hh @@ -1,5 +1,6 @@ #pragma once +#include "pm.hh" #include "pms.hh" #include "utils.hh" #include @@ -12,33 +13,12 @@ struct Measurement { const char *sensor; union { float temp; - struct { - struct { - uint16_t pm1Mcg; - uint16_t pm2Mcg; - uint16_t pm10Mcg; - } std; - struct { - uint16_t pm1Mcg; - uint16_t pm2Mcg; - uint16_t pm10Mcg; - } atm; - struct { - uint16_t pm03Count; - uint16_t pm05Count; - uint16_t pm1Count; - uint16_t pm2Count; - uint16_t pm5Count; - uint16_t pm10Count; - } cnt; - } pm; + Pm pm; }; void fixTime(); - void set(const pms::Response &res); - - void set(const pms::ResponseSum &sum); + template void set(const Pm &rhs) { pm = rhs; } [[nodiscard]] const char *getType() const; diff --git a/firmware/main/pm.hh b/firmware/main/pm.hh new file mode 100644 index 0000000..eab21b4 --- /dev/null +++ b/firmware/main/pm.hh @@ -0,0 +1,67 @@ +#pragma once + +#include + +template struct Pm { + struct { + T pm1Mcg; + T pm2Mcg; + T pm10Mcg; + } std; + struct { + T pm1Mcg; + T pm2Mcg; + T pm10Mcg; + } atm; + struct { + T pm03Count; + T pm05Count; + T pm1Count; + T pm2Count; + T pm5Count; + T pm10Count; + } cnt; + + template Pm &operator=(const Pm &rhs) { + return map( + rhs, [](const R in, const T out) -> T { return static_cast(in); }); + } + + template Pm &operator+=(const Pm &rhs) { + return map(rhs, [](const R in, const T out) -> T { + return static_cast(in) + out; + }); + } + + template Pm &operator/=(const R divisor) { + return map([divisor](const T val) { return val / divisor; }); + } + +private: + template + using BinaryMapper = std::function; + + template using UnaryMapper = std::function; + + template Pm &map(const UnaryMapper &mapper) { + T *dst = reinterpret_cast(this); + T *const dstEnd = dst + sizeof(Pm) / sizeof(T); + + std::transform(dst, dstEnd, dst, mapper); + + return *this; + } + + template + Pm &map(const Pm &rhs, const BinaryMapper &mapper) { + T *dst = reinterpret_cast(this); + const R *src = reinterpret_cast(&rhs); + const R *const srcEnd = src + sizeof(Pm) / sizeof(R); + + for (; src != srcEnd; ++dst, ++src) { + *dst = mapper(*src, *dst); + } + + return *this; + } +} __attribute__((packed)); diff --git a/firmware/main/pms.cc b/firmware/main/pms.cc index fe37f76..d8abbab 100644 --- a/firmware/main/pms.cc +++ b/firmware/main/pms.cc @@ -118,7 +118,7 @@ void Response::swapBytes() { if (sendEach) { ms.time = getTimestamp(); - ms.set(res); + ms.set(res.pm); if (!station.queue->putRetrying(ms)) { ESP_LOGE(logTag, "could not queue particulate measurement"); } @@ -126,8 +126,8 @@ void Response::swapBytes() { sum.addMeasurement(res); } - ESP_LOGI(logTag, "read PM: 1=%dµg, 2.5=%dµg, 10=%dµg", res.pm1McgAtm, - res.pm2McgAtm, res.pm10McgAtm); + ESP_LOGI(logTag, "read PM: 1=%dµg, 2.5=%dµg, 10=%dµg", res.pm.atm.pm1Mcg, + res.pm.atm.pm2Mcg, res.pm.atm.pm10Mcg); ++successful; } @@ -148,7 +148,8 @@ void Response::swapBytes() { lastWake = xTaskGetTickCount(); } else { if (!sendEach) { - ms.set(sum); + sum.calcAvg(); + ms.set(sum.pm); ESP_LOGI(logTag, "avg PM: 1=%u, 2.5=%u, 10=%u", ms.pm.atm.pm1Mcg, ms.pm.atm.pm2Mcg, ms.pm.atm.pm10Mcg); @@ -203,24 +204,17 @@ void Station::start(Queue &msQueue) { } void ResponseSum::addMeasurement(const Response &resp) { - atm.pm1Mcg += resp.pm1McgAtm; - atm.pm2Mcg += resp.pm2McgAtm; - atm.pm10Mcg += resp.pm10McgAtm; - - std.pm1Mcg += resp.pm1McgStd; - std.pm2Mcg += resp.pm2McgStd; - std.pm10Mcg += resp.pm10McgStd; - - cnt.pm03Count += resp.pm03Count; - cnt.pm05Count += resp.pm05Count; - cnt.pm1Count += resp.pm1Count; - cnt.pm2Count += resp.pm2Count; - cnt.pm5Count += resp.pm5Count; - cnt.pm10Count += resp.pm10Count; - + pm += resp.pm; ++count; } void ResponseSum::reset() { memset(this, 0, sizeof(*this)); } +void ResponseSum::calcAvg() { + if (count > 0) { + pm /= count; + count = 0; + } +} + } // namespace pms diff --git a/firmware/main/pms.hh b/firmware/main/pms.hh index 34e7157..13fc7d6 100644 --- a/firmware/main/pms.hh +++ b/firmware/main/pms.hh @@ -1,5 +1,6 @@ #pragma once +#include "pm.hh" #include "queue.hh" #include #include @@ -23,18 +24,7 @@ struct Command { struct Response { uint16_t magic; uint16_t frameLen; - uint16_t pm1McgStd; - uint16_t pm2McgStd; - uint16_t pm10McgStd; - uint16_t pm1McgAtm; - uint16_t pm2McgAtm; - uint16_t pm10McgAtm; - uint16_t pm03Count; - uint16_t pm05Count; - uint16_t pm1Count; - uint16_t pm2Count; - uint16_t pm5Count; - uint16_t pm10Count; + Pm pm; uint16_t reserved; uint16_t checksum; @@ -56,7 +46,7 @@ struct Station { esp_err_t flushInput(); - esp_err_t flushOutput(const TickType_t wait); + esp_err_t flushOutput(TickType_t wait); void start(Queue &msQueue); @@ -68,28 +58,13 @@ private: }; struct ResponseSum { + Pm pm; uint32_t count; - struct { - uint32_t pm1Mcg; - uint32_t pm2Mcg; - uint32_t pm10Mcg; - } std; - struct { - uint32_t pm1Mcg; - uint32_t pm2Mcg; - uint32_t pm10Mcg; - } atm; - struct { - uint32_t pm03Count; - uint32_t pm05Count; - uint32_t pm1Count; - uint32_t pm2Count; - uint32_t pm5Count; - uint32_t pm10Count; - } cnt; void addMeasurement(const Response &resp); + void calcAvg(); + void reset(); };