Skip to content

Commit

Permalink
Less copypasta in PM measurement calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
hg committed Nov 22, 2020
1 parent d637cb0 commit 930257e
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 121 deletions.
6 changes: 3 additions & 3 deletions firmware/main/commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string_view> tokens;
CommandArgs tokens;

const auto end = msg.data.cend();
for (auto begin = msg.data.cbegin(); begin != end;) {
Expand All @@ -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;
}

Expand Down
20 changes: 9 additions & 11 deletions firmware/main/dallas.cc
Original file line number Diff line number Diff line change
@@ -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<DS18B20_Info> findSensor(const OneWireBus &owb) {
Expand Down Expand Up @@ -44,25 +42,24 @@ static std::unique_ptr<DS18B20_Info> 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);
}
}

Expand All @@ -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<OneWireBus, decltype(&owb_uninitialize)> owb{
owb_rmt_initialize(&driver_info, sensor.pin, sensor.txChan,
sensor.rxChan),
Expand Down
34 changes: 0 additions & 34 deletions firmware/main/measurement.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
26 changes: 3 additions & 23 deletions firmware/main/measurement.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "pm.hh"
#include "pms.hh"
#include "utils.hh"
#include <ctime>
Expand All @@ -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<uint16_t> pm;
};

void fixTime();

void set(const pms::Response &res);

void set(const pms::ResponseSum &sum);
template <typename R> void set(const Pm<R> &rhs) { pm = rhs; }

[[nodiscard]] const char *getType() const;

Expand Down
67 changes: 67 additions & 0 deletions firmware/main/pm.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <functional>

template <typename T> 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 <typename R> Pm<T> &operator=(const Pm<R> &rhs) {
return map<R>(
rhs, [](const R in, const T out) -> T { return static_cast<T>(in); });
}

template <typename R> Pm<T> &operator+=(const Pm<R> &rhs) {
return map<R>(rhs, [](const R in, const T out) -> T {
return static_cast<T>(in) + out;
});
}

template <typename R> Pm<T> &operator/=(const R divisor) {
return map<R>([divisor](const T val) { return val / divisor; });
}

private:
template <typename R>
using BinaryMapper = std::function<T(const R in, const T out)>;

template <typename R> using UnaryMapper = std::function<T(const T val)>;

template <typename R> Pm<T> &map(const UnaryMapper<R> &mapper) {
T *dst = reinterpret_cast<T *>(this);
T *const dstEnd = dst + sizeof(Pm<T>) / sizeof(T);

std::transform(dst, dstEnd, dst, mapper);

return *this;
}

template <typename R>
Pm<T> &map(const Pm<R> &rhs, const BinaryMapper<R> &mapper) {
T *dst = reinterpret_cast<T *>(this);
const R *src = reinterpret_cast<const R *>(&rhs);
const R *const srcEnd = src + sizeof(Pm<R>) / sizeof(R);

for (; src != srcEnd; ++dst, ++src) {
*dst = mapper(*src, *dst);
}

return *this;
}
} __attribute__((packed));
32 changes: 13 additions & 19 deletions firmware/main/pms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ 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");
}
} else {
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;
}
Expand All @@ -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);

Expand Down Expand Up @@ -203,24 +204,17 @@ void Station::start(Queue<Measurement> &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
37 changes: 6 additions & 31 deletions firmware/main/pms.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "pm.hh"
#include "queue.hh"
#include <driver/gpio.h>
#include <driver/uart.h>
Expand All @@ -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<uint16_t> pm;
uint16_t reserved;
uint16_t checksum;

Expand All @@ -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<Measurement> &msQueue);

Expand All @@ -68,28 +58,13 @@ private:
};

struct ResponseSum {
Pm<uint32_t> 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();
};

Expand Down

0 comments on commit 930257e

Please sign in to comment.