Skip to content

Commit

Permalink
Move to C++17
Browse files Browse the repository at this point in the history
  • Loading branch information
hg committed Nov 18, 2020
1 parent a34ea66 commit d596258
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 129 deletions.
2 changes: 1 addition & 1 deletion firmware/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ idf_component_register(
EMBED_TXTFILES "ca.pem"
)

target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-missing-field-initializers)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-missing-field-initializers -std=gnu++17)

19 changes: 11 additions & 8 deletions firmware/main/commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

using CommandArgs = std::vector<std::string_view>;

static bool handlePing(mqtt::Client &client, const mqtt::Message &msg) {
return client.send(msg.respTopic, appSettings.devName);
}
Expand All @@ -21,17 +23,17 @@ static bool handlePing(mqtt::Client &client, const mqtt::Message &msg) {

static bool handleReadSettings(mqtt::Client &client, const mqtt::Message &msg) {
const std::string json = appSettings.format();
client.send(msg.respTopic, json.c_str());
client.send(msg.respTopic, json);
return true;
}

static bool handleWriteSetting(mqtt::Client &client, const mqtt::Message &msg,
const std::vector<std::string> &args) {
const CommandArgs &args) {
if (args.size() != 3) {
client.send(msg.respTopic, "usage: setting/set name_no_spaces value_also");
return false;
}
const esp_err_t err = appSettings.write(args[1].c_str(), args[2].c_str());
const esp_err_t err = appSettings.write(args[1], args[2]);
if (err == ESP_OK) {
client.send(msg.respTopic, "setting set");
} else {
Expand All @@ -41,14 +43,14 @@ static bool handleWriteSetting(mqtt::Client &client, const mqtt::Message &msg,
}

static bool handleOta(mqtt::Client &client, const mqtt::Message &msg,
const std::vector<std::string> &args) {
const CommandArgs &args) {
if (args.size() != 2) {
client.send(msg.respTopic, "usage: ota https://server/path.bin");
return false;
}

const esp_http_client_config_t config{
.url = args[1].c_str(),
.url = args[1].data(),
.cert_pem = caPemStart,
};

Expand All @@ -72,13 +74,14 @@ static bool handleUnknown(mqtt::Client &client, const mqtt::Message &msg) {
}

static bool handleMessage(mqtt::Client &client, const mqtt::Message &msg) {
std::vector<std::string> tokens;
std::vector<std::string_view> tokens;

const auto end = msg.data.cend();
for (auto begin = msg.data.cbegin(); begin != end;) {
const auto nextSpace = std::find_if(begin, end, isspace);
if (nextSpace != begin) {
tokens.push_back(std::string{begin, nextSpace});
const std::string_view::size_type len = nextSpace - begin;
tokens.emplace_back(begin.base(), len);
if (nextSpace == end) {
break;
}
Expand All @@ -91,7 +94,7 @@ static bool handleMessage(mqtt::Client &client, const mqtt::Message &msg) {
return false;
}

const std::string &command = tokens.front();
const std::string_view &command = tokens.front();

if (command == "ota") {
return handleOta(client, msg, tokens);
Expand Down
102 changes: 49 additions & 53 deletions firmware/main/dallas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,10 @@ static const int delayTemp = secToTicks(CONFIG_TEMPERATURE_PERIOD_SECONDS);

namespace ds {

void TempSensor::start(Queue<Measurement> &msQueue) {
queue = &msQueue;
char buf[24];
snprintf(buf, sizeof(buf), "ms_temp_%d", pin);
xTaskCreate(collectionTask, buf, KiB(2), this, 2, nullptr);
}

[[noreturn]] void TempSensor::collectionTask(void *const arg) {
TempSensor &sensor = *reinterpret_cast<TempSensor *>(arg);

ESP_LOGI(logTag, "starting temp collection task for %s", sensor.name);

while (true) {
vTaskDelay(secToTicks(2));

owb_rmt_driver_info driver_info;
OneWireBus *owb = owb_rmt_initialize(&driver_info, sensor.pin,
sensor.txChan, sensor.rxChan);
owb_use_crc(owb, true);

DS18B20_Info *device = searchTempSensor(owb);

if (device) {
runTempMeasurements(device, &sensor);
ds18b20_free(&device);
}

owb_uninitialize(owb);

ESP_LOGE(logTag, "sensor %s failed, restarting", sensor.name);
}
}

DS18B20_Info *TempSensor::searchTempSensor(const OneWireBus *const owb) {
static std::unique_ptr<DS18B20_Info> findSensor(const OneWireBus &owb) {
for (bool found = false; !found;) {
OneWireBus_SearchState search_state;
const owb_status status = owb_search_first(owb, &search_state, &found);
OneWireBus_SearchState searchState;
const owb_status status = owb_search_first(&owb, &searchState, &found);

if (status != OWB_STATUS_OK) {
ESP_LOGE(logTag, "owb search failed: %d", status);
Expand All @@ -55,44 +22,42 @@ DS18B20_Info *TempSensor::searchTempSensor(const OneWireBus *const owb) {
}
}

OneWireBus_ROMCode rom_code;
const owb_status status = owb_read_rom(owb, &rom_code);
OneWireBus_ROMCode romCode;
const owb_status status = owb_read_rom(&owb, &romCode);

if (status != OWB_STATUS_OK) {
ESP_LOGE(logTag, "could not read ROM code: %d", status);
return nullptr;
}

char rom_code_s[OWB_ROM_CODE_STRING_LENGTH];
owb_string_from_rom_code(rom_code, rom_code_s, sizeof(rom_code_s));
ESP_LOGI(logTag, "found device 0x%s", rom_code_s);
char romCodeStr[OWB_ROM_CODE_STRING_LENGTH];
owb_string_from_rom_code(romCode, romCodeStr, sizeof(romCodeStr));
ESP_LOGI(logTag, "found device 0x%s", romCodeStr);

// Create DS18B20 devices on the 1-Wire bus
DS18B20_Info *const device = ds18b20_malloc(); // heap allocation
ds18b20_init_solo(device, owb); // only one device on bus
ds18b20_use_crc(device, true); // enable CRC check on all reads
ds18b20_set_resolution(device, DS18B20_RESOLUTION_12_BIT);
std::unique_ptr<DS18B20_Info> device{ds18b20_malloc()};

ds18b20_init_solo(device.get(), &owb);
ds18b20_use_crc(device.get(), true);
ds18b20_set_resolution(device.get(), DS18B20_RESOLUTION_12_BIT);

return device;
}

void TempSensor::runTempMeasurements(const DS18B20_Info *device,
const TempSensor *const config) {
void TempSensor::runMeasurements(const DS18B20_Info &device) {
int errCount = 0;
Measurement ms{.type = MeasurementType::Temperature,
.sensor = config->name};
Measurement ms{.type = MeasurementType::TEMPERATURE, .sensor = name};
TickType_t lastWakeTime = xTaskGetTickCount();

while (errCount < 4) {
const DS18B20_ERROR err = ds18b20_convert_and_read_temp(device, &ms.temp);
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", config->name, err);
ESP_LOGW(logTag, "measurement failed in %s, err %d", name, err);
} else {
errCount = 0;
ms.time = getTimestamp();
if (!config->queue->putRetrying(ms)) {
if (!queue->putRetrying(ms)) {
ESP_LOGE(logTag, "could not put temp measurement into queue");
}
}
Expand All @@ -101,4 +66,35 @@ void TempSensor::runTempMeasurements(const DS18B20_Info *device,
}
}

[[noreturn]] void TempSensor::collectionTask(void *const arg) {
TempSensor &sensor = *reinterpret_cast<TempSensor *>(arg);

ESP_LOGI(logTag, "starting temp collection task for %s", sensor.name);

for (owb_rmt_driver_info driver_info;;) {
vTaskDelay(secToTicks(2));

std::unique_ptr<OneWireBus, decltype(&owb_uninitialize)> owb{
owb_rmt_initialize(&driver_info, sensor.pin, sensor.txChan,
sensor.rxChan),
owb_uninitialize};

owb_use_crc(owb.get(), true);

const std::unique_ptr<DS18B20_Info> device = findSensor(*owb);
if (device) {
sensor.runMeasurements(*device);
}

ESP_LOGE(logTag, "sensor %s failed, restarting", sensor.name);
}
}

void TempSensor::start(Queue<Measurement> &msQueue) {
queue = &msQueue;
char buf[24];
snprintf(buf, sizeof(buf), "temp_%s", name);
xTaskCreate(collectionTask, buf, KiB(2), this, 2, nullptr);
}

} // namespace ds
6 changes: 2 additions & 4 deletions firmware/main/dallas.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <driver/gpio.h>
#include <driver/rmt.h>
#include <ds18b20.h>
#include <memory>

namespace ds {

Expand All @@ -20,10 +21,7 @@ struct TempSensor {
private:
[[noreturn]] static void collectionTask(void *arg);

static DS18B20_Info *searchTempSensor(const OneWireBus *owb);

static void runTempMeasurements(const DS18B20_Info *device,
const TempSensor *config);
void runMeasurements(const DS18B20_Info &device);
};

} // namespace ds
14 changes: 7 additions & 7 deletions firmware/main/measurement.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ void Measurement::set(const pms::ResponseSum &sum) {

const char *Measurement::getType() const {
switch (type) {
case MeasurementType::Temperature:
case MeasurementType::TEMPERATURE:
return "meas/temp";

case MeasurementType::Particulates:
case MeasurementType::PARTICULATES:
return "meas/part";

default:
Expand All @@ -59,18 +59,18 @@ const char *Measurement::getType() const {
}
}

bool Measurement::formatMsg(char *const msg, const size_t len) const {
bool Measurement::formatMsg(char *const buf, const size_t size) const {
switch (type) {
case MeasurementType::Temperature: {
case MeasurementType::TEMPERATURE: {
constexpr auto tpl = R"({"dev":"%s","time":%ld,"sens":"%s","temp":%f})";
snprintf(msg, len, tpl, appSettings.devName, time, sensor, temp);
snprintf(buf, size, tpl, appSettings.devName, time, sensor, temp);
return true;
}

case MeasurementType::Particulates: {
case MeasurementType::PARTICULATES: {
constexpr auto tpl =
R"({"dev":"%s","time":%ld,"sens":"%s","std":{"pm1":%u,"pm2.5":%u,"pm10":%u},"atm":{"pm1":%u,"pm2.5":%u,"pm10":%u},"cnt":{"pm0.3":%u,"pm0.5":%u,"pm1":%u,"pm2.5":%u,"pm5":%u,"pm10":%u}})";
snprintf(msg, len, tpl, appSettings.devName, time, sensor, pm.std.pm1Mcg,
snprintf(buf, size, tpl, appSettings.devName, time, sensor, pm.std.pm1Mcg,
pm.std.pm2Mcg, pm.std.pm10Mcg, pm.atm.pm1Mcg, pm.atm.pm2Mcg,
pm.atm.pm10Mcg, pm.cnt.pm03Count, pm.cnt.pm05Count,
pm.cnt.pm1Count, pm.cnt.pm2Count, pm.cnt.pm5Count,
Expand Down
6 changes: 3 additions & 3 deletions firmware/main/measurement.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "utils.hh"
#include <ctime>

enum class MeasurementType { Temperature, Particulates };
enum class MeasurementType { TEMPERATURE, PARTICULATES };

struct Measurement {
MeasurementType type;
Expand Down Expand Up @@ -40,7 +40,7 @@ struct Measurement {

void set(const pms::ResponseSum &sum);

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

bool formatMsg(char *msg, size_t len) const;
bool formatMsg(char *buf, size_t size) const;
};
19 changes: 10 additions & 9 deletions firmware/main/mqtt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

namespace mqtt {

esp_err_t Client::handleEvent(const esp_mqtt_event_handle_t evt) {
esp_err_t Client::handleEvent(esp_mqtt_event_handle_t evt) {
Client &client = *reinterpret_cast<Client *>(evt->user_context);

switch (evt->event_id) {
case MQTT_EVENT_CONNECTED:
client.setState(MqttState::Ready);
client.setState(MqttState::READY);
client.subscribe("cmd/*", 2);
client.subscribe(client.cmdTopic.c_str(), 2);
client.subscribe(client.cmdTopic, 2);
ESP_LOGI(logTag, "mqtt connected");
break;

case MQTT_EVENT_DISCONNECTED:
client.clearState(MqttState::Ready);
client.clearState(MqttState::READY);
ESP_LOGI(logTag, "mqtt disconnected");
break;

Expand Down Expand Up @@ -81,13 +81,14 @@ Client::~Client() {
}

void Client::waitReady() const {
xEventGroupWaitBits(event, static_cast<EventBits_t>(MqttState::Ready), false,
xEventGroupWaitBits(event, static_cast<EventBits_t>(MqttState::READY), false,
false, portMAX_DELAY);
}

bool Client::send(const std::string &topic, const char *const data) {
bool Client::send(std::string_view topic, std::string_view data) {
for (int result = -1; result < 0;) {
result = esp_mqtt_client_publish(handle, topic.c_str(), data, 0, 1, 1);
result = esp_mqtt_client_publish(handle, topic.data(), data.data(),
data.length(), 1, 1);
if (result < 0) {
ESP_LOGI(logTag, "mqtt publish failed, retrying");
vTaskDelay(secToTicks(5));
Expand All @@ -105,8 +106,8 @@ void Client::clearState(const MqttState bits) {
xEventGroupClearBits(event, static_cast<EventBits_t>(bits));
}

bool Client::subscribe(const char *topic, int qos) {
return esp_mqtt_client_subscribe(handle, topic, qos) != ESP_OK;
bool Client::subscribe(std::string_view topic, int qos) {
return esp_mqtt_client_subscribe(handle, topic.data(), qos) != ESP_OK;
}

Message Client::receive() { return *msgQueue.take(); }
Expand Down
13 changes: 7 additions & 6 deletions firmware/main/mqtt.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
#include <freertos/event_groups.h>
#include <mqtt_client.h>
#include <string>
#include <string_view>
#include <vector>

namespace mqtt {

enum class MqttState : EventBits_t {
Ready = BIT0,
READY = BIT0,
};

struct Message {
Expand All @@ -19,7 +20,7 @@ struct Message {
std::string respTopic;
std::string data;

bool isBroadcast() const { return topic == "cmd/*"; }
[[nodiscard]] bool isBroadcast() const { return topic == "cmd/*"; }
};

class Client {
Expand All @@ -35,11 +36,11 @@ public:

void waitReady() const;

bool send(const std::string &topic, const char *data);
bool send(std::string_view topic, std::string_view data);

Message receive();
[[nodiscard]] Message receive();

bool subscribe(const char *topic, int qos);
bool subscribe(std::string_view topic, int qos);

private:
void clearState(MqttState bits);
Expand All @@ -48,7 +49,7 @@ private:

static esp_err_t handleEvent(esp_mqtt_event_handle_t evt);

Queue<Message*> msgQueue{10};
Queue<Message *> msgQueue{10};
esp_mqtt_client_handle_t handle;
EventGroupHandle_t event;
const char *cert;
Expand Down
Loading

0 comments on commit d596258

Please sign in to comment.