#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" static void esp_log_backend(const std::vector<qthing::measured::MeasureResult>& data) { for (auto const& d: data) { ESP_LOGI("measured", "name=%s type=%s unit=%s value=%f", d.sensor_name.c_str(), d.sensor_type.c_str(), d.sensor_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)(); } qthing::measured::MeasureResult::MeasureResult(const std::string& name, const std::string& type, const std::string& unit, float value) : value(value), sensor_name(name), sensor_type(type), sensor_unit(unit) {} qthing::measured::Sensor::Sensor(const std::string& name, const std::string& type, const std::string& unit) : name(name), type(type), unit(unit) {} qthing::measured::Sensor::skip_measurement_t qthing::measured::Sensor::prepare_next_measurement() { return(no_skip); } qthing::measured::MeasureResult qthing::measured::Sensor::create_result(float value) { return(qthing::measured::MeasureResult(this->name, this->type, this->unit, value)); } /* * 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::MeasureResult> data; for (auto& sensor: sensors) { data.push_back(sensor->measure()); } 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 *sensor) { this->sensors.push_back(sensor); } 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::MeasureResult>& 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 *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::MeasureResult>& 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.sensor_name.c_str()) + std::string("/") + std::string(d.sensor_type.c_str()); publish_message(topic, message); } } }