#include "measured.h" #include <string> #include <vector> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "qthing.h" #include "mqtt_common.h" typedef struct { std::string name; std::string type; std::string unit; qthing::measured::sensor_t sensor; } sensor_config_t; static void esp_log_backend(const std::vector<qthing::measured::sensor_data_t>& data) { for (auto const& d: data) { ESP_LOGI("measured", "name=%s type=%s unit=%s value=%f", d.name->c_str(), d.type->c_str(), d.unit->c_str(), d.value); } } static uint16_t next_daemon = 0; static void measured_wrapper(void *parameter) { std::function<void()> *f = (std::function<void()> *)parameter; (*f)(); } /* * Measured implementation */ qthing::measured::Measured::Measured() { this->backend = esp_log_backend; this->register_backend(qthing::measured::backend::mqtt); // TODO: move somewhere else! char task_name[16]; sprintf(task_name, "measured[%d]", next_daemon++); // TODO: increment thread-safe! std::function<void()> f = std::bind(&qthing::measured::Measured::Measured::measured, this); std::function<void()> *_f = new std::function<void()>(f); xTaskCreate(measured_wrapper, task_name, 8192, (void*)_f, 1, NULL); } void qthing::measured::Measured::measured() { TickType_t lastWakeTime = xTaskGetTickCount(); while(true) { std::vector<qthing::measured::sensor_data_t> data; for (auto const& sensor: sensors) { qthing::measured::sensor_data_t tmp = { .name = &sensor.name, .type = &sensor.type, .unit = &sensor.unit, .value = sensor.sensor() }; data.push_back(tmp); } this->backend(data); vTaskDelayUntil(&lastWakeTime, this->measure_period / portTICK_PERIOD_MS); } } void qthing::measured::Measured::register_sensor(std::string name, std::string type, std::string unit, qthing::measured::sensor_t sensor) { sensor_config_t cfg = { .name = name, .type = type, .unit = unit, .sensor = sensor }; this->sensors.push_back(cfg); } void qthing::measured::Measured::register_backend(qthing::measured::backend_t new_backend) { qthing::measured::backend_t old_backend = this->backend; this->backend = [old_backend, new_backend](const std::vector<qthing::measured::sensor_data_t>& data) { old_backend(data); new_backend(data); }; } void qthing::measured::Measured::set_measure_period(uint16_t period) { this->measure_period = period; } /* * Global default instance */ static qthing::measured::Measured *md = NULL; static void start_measured() { if (md == NULL) { // TODO: thread-safe! md = new qthing::measured::Measured(); } } void qthing::measured::register_sensor(std::string name, std::string type, std::string unit, qthing::measured::sensor_t sensor) { start_measured(); md->register_sensor(name, type, unit, sensor); } void qthing::measured::register_backend(qthing::measured::backend_t new_backend) { start_measured(); md->register_backend(new_backend); } void qthing::measured::set_measure_period(uint16_t period) { start_measured(); md->set_measure_period(period); } /* * Predefined backends */ void qthing::measured::backend::mqtt(const std::vector<qthing::measured::sensor_data_t>& data) { if (is_mqtt_connected()) { for (auto const& d: data) { char message[16]; sprintf(message, "%0.2f", d.value); std::string topic = std::string(DEVICE_NAMESPACE) + std::string(d.name->c_str()) + std::string("/") + std::string(d.type->c_str()); publish_message(topic, message); } } }