From 633fb6b368297596153552ab2aa83f7bd0ac2f1f Mon Sep 17 00:00:00 2001 From: Jochen Vothknecht <jochen3120@gmail.com> Date: Tue, 4 Jan 2022 08:38:12 +0100 Subject: [PATCH] Begin metrics development (untested) --- 10W/TransportProtection.scad | 25 +++-- CLC-qthing/CMakeLists.txt | 2 + CLC-qthing/CyanLight.hpp | 1 - CLC-qthing/SiliconTorch/FxCyanF.cpp | 14 ++- CLC-qthing/SiliconTorch/Metrics.cpp | 151 ++++++++++++++++++++++++++++ CLC-qthing/SiliconTorch/Metrics.hpp | 82 +++++++++++++++ CLC-qthing/device_config.h | 2 +- CLC-qthing/device_main.cpp | 34 ++++--- 8 files changed, 284 insertions(+), 27 deletions(-) create mode 100644 CLC-qthing/SiliconTorch/Metrics.cpp create mode 100644 CLC-qthing/SiliconTorch/Metrics.hpp diff --git a/10W/TransportProtection.scad b/10W/TransportProtection.scad index 96b1990..69e87ca 100644 --- a/10W/TransportProtection.scad +++ b/10W/TransportProtection.scad @@ -1,15 +1,19 @@ +use <../WebWeaver/scad/Util.scad>; + + $fs = 0.5; $fa = 1.0; -pcb_w = 40.5; -pcb_h = 67.5; -pcb_r = 5; // edge radius -pcb_off = 0.4; -pcb_t = 5; // thickness including LED and inductor - +pcb_w = 40.5; +pcb_h = 67.5; +pcb_r = 5; // edge radius +pcb_off = 0.4; +pcb_t = 5; // thickness including LED and inductor +pcb_conn_w = 20; +pcb_conn_h = 3; module pcb(w=pcb_w, h=pcb_h, r=pcb_r, off=pcb_off) { @@ -18,7 +22,14 @@ module pcb(w=pcb_w, h=pcb_h, r=pcb_r, off=pcb_off) { _h = h + 2*off; _r = r + off; - hull() for (tx=[_r, _w-_r], ty=[_r, _h-_r]) translate([tx, ty, 0]) circle(r=r); + hull() { + + // function of WebWeaver + roundRect(_w, _h, _r, true, true); + + translate([0, -_h/2 +1 -pcb_conn_h, 0]) square([pcb_conn_w, pcb_conn_h + 1], center=true); + + } } module pcbBox(wi, hi, ri, _str) { diff --git a/CLC-qthing/CMakeLists.txt b/CLC-qthing/CMakeLists.txt index 8b29cc8..bc7bdbc 100644 --- a/CLC-qthing/CMakeLists.txt +++ b/CLC-qthing/CMakeLists.txt @@ -8,4 +8,6 @@ idf_component_register( REQUIRES main ) + component_compile_options(-std=c++17) +component_compile_options(-Wno-reorder) diff --git a/CLC-qthing/CyanLight.hpp b/CLC-qthing/CyanLight.hpp index 300ce77..5f40a0f 100644 --- a/CLC-qthing/CyanLight.hpp +++ b/CLC-qthing/CyanLight.hpp @@ -1,7 +1,6 @@ #pragma once // TODO: should we include <cinttypes> here or accepts its ingress via FxCyanF.hpp ??? - #include "SiliconTorch/FxCyanF.hpp" diff --git a/CLC-qthing/SiliconTorch/FxCyanF.cpp b/CLC-qthing/SiliconTorch/FxCyanF.cpp index d212edf..806ee40 100644 --- a/CLC-qthing/SiliconTorch/FxCyanF.cpp +++ b/CLC-qthing/SiliconTorch/FxCyanF.cpp @@ -1,5 +1,9 @@ #include "FxCyanF.hpp" +#include "esp_err.h" +#include "esp_log.h" +#include "driver/ledc.h" + #include <qthing> #include <qthing/mqtt_common.hpp> @@ -9,9 +13,7 @@ #include <algorithm> #include <functional> -#include "esp_err.h" -#include "esp_log.h" -#include "driver/ledc.h" +#include "Metrics.hpp" using namespace qthing; @@ -33,7 +35,11 @@ static float bytes2float(const char *bytes) { } -SiliconTorch::FxCyanF::FxCyanF(uint32_t baseChannel) : baseChannel(baseChannel) { +SiliconTorch::FxCyanF::FxCyanF(uint32_t baseChannel) : metrics(Metrics::Metrics("fxCyan", 60*60)), baseChannel(baseChannel) { + + metrics.registerMetric("frames", "FrameCounter"); + metrics.registerMetric("errors", "ErrorCounter"); + // TODO: make vector! this->channels = new SiliconTorch::Impl::PWMChannel*[MAX_CHANNELS]; diff --git a/CLC-qthing/SiliconTorch/Metrics.cpp b/CLC-qthing/SiliconTorch/Metrics.cpp new file mode 100644 index 0000000..12c2a42 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Metrics.cpp @@ -0,0 +1,151 @@ +#include "Metrics.hpp" + +#include "freertos/FreeRTOS.h" +// #include "freertos/semphr.h" +#include "freertos/task.h" + +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_err.h" +#include "esp_log.h" + +#include <ctime> +#include <climits> +#include <cinttypes> + + +static const char* TAG = "Metrics"; + + +static uint8_t nextTask = 0; +static void methodTaskWrapper(void *parameter) { + std::function<void()> *f = (std::function<void()> *)parameter; + (*f)(); +} + + +namespace SiliconTorch { + + namespace Metrics { + + Metrics::Metrics(const std::string& nameSpace, uint32_t saveInterval) : nameSpace(nameSpace), saveInterval(saveInterval) { + + nvs_flash_init(); + nvs_open(nameSpace.c_str(), NVS_READWRITE, &this->nvs); + + + + char taskName[64]; + snprintf(taskName, sizeof(taskName), "Metrics[%i]", nextTask++); // TODO: increment thread-safe! + + std::function<void()> f = std::bind(&SiliconTorch::Metrics::Metrics::tickTask, this); + std::function<void()> *_f = new std::function<void()>(f); + xTaskCreate(methodTaskWrapper, taskName, 8192, (void*)_f, 1, NULL); + + } + + + void Metrics::registerMetric(const std::string& shortName, const std::string& fullName) { + + auto result = counters.find(shortName); + if (result != counters.end()) { + ESP_LOGW(TAG, "Can't register Metric[ %s ]: Already exists", shortName.c_str()); + } else { + counters[shortName] = new CounterMetric(shortName, fullName, 10, 10); + } + } + + + void Metrics::saveData() { + // TODO: implementation! + + lastSaved = std::time(NULL); + } + + void Metrics::tickTask() { + + while (true) { + + std::time_t now = std::time(NULL); + if (now - lastSaved > saveInterval) saveData(); + + vTaskDelay((tickInterval * 1000) / portTICK_PERIOD_MS); + } + } + + + uint64_t getCounter(const std::string& shortName) { + return 0; + } + + + CounterMetric::CounterMetric(const std::string& shortName, const std::string& fullName, uint32_t saveInterval, uint32_t publishInterval) : + shortName(shortName), fullName(fullName), saveInterval(saveInterval), publishInterval(publishInterval) { + + // TODO: implement! + + // TODO: implement? what to do??? + } + + + void CounterMetric::load(nvs_handle_t* nvs) { + lastSaved = std::time(NULL); + + nvs_get_u64(*nvs, shortName.c_str(), &this->value); + } + + void CounterMetric::save(nvs_handle_t* nvs) { + if (std::time(NULL) - lastSaved > saveInterval) forceSave(nvs); + } + + // TODO: synchronize! + void CounterMetric::forceSave(nvs_handle_t* nvs) { + lastSaved = std::time(NULL); + dirty = false; + + esp_err_t err = nvs_set_u64(*nvs, shortName.c_str(), this->value); + + if (true) { + // if (err != ESP_OK) { // !!!!!! + const char* errorName = esp_err_to_name(err); + ESP_LOGE(TAG, "Error[ %s ] saving Metric[ %s ]", errorName, fullName.c_str()); + } + } + + + void CounterMetric::inc() { + if (value < ULLONG_MAX) { + dirty = true; + value++; + } + } + + void CounterMetric::dec() { + if (value > 0) { + dirty = true; + value--; + } + } + + // pre-increment + uint64_t& CounterMetric::CounterMetric::operator++() { + inc(); return value; + } + + // pre-decrement + uint64_t& CounterMetric::CounterMetric::operator--() { + dec(); return value; + } + + // post-increment + uint64_t CounterMetric::CounterMetric::operator++(int ignored) { + uint64_t out = value; inc(); return out; + } + + // post-decrement + uint64_t CounterMetric::CounterMetric::operator--(int ignored) { + uint64_t out = value; dec(); return out; + } + + } +} diff --git a/CLC-qthing/SiliconTorch/Metrics.hpp b/CLC-qthing/SiliconTorch/Metrics.hpp new file mode 100644 index 0000000..b3b81a0 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Metrics.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include <map> +#include <ctime> +#include <string> +#include <functional> + +#include "nvs.h" + + + +namespace SiliconTorch { + + namespace Metrics { + + typedef std::function<void()> Incrementer; + + class CounterMetric { + public: + CounterMetric(const std::string& shortName, const std::string& fullName, uint32_t saveInterval, uint32_t publishInterval); + + const std::string& fullName; + const std::string& shortName; + + void inc(); + void dec(); + + void load(nvs_handle_t* nvs); // load value from NVS + void save(nvs_handle_t* nvs); // saves only if enoughg time elapsed + void forceSave(nvs_handle_t* nvs); // saves value immediately + + uint64_t& operator++(); // pre-increment + uint64_t& operator--(); // pre-decrement + + uint64_t operator++(int); // post-increment + uint64_t operator--(int); // post-decrement + + private: + uint64_t value = 0; + + bool dirty = false; + + uint32_t saveInterval; + uint32_t publishInterval; + + std::time_t lastSaved; + std::time_t lastPublished; + }; + + class Metrics { + public: + Metrics(const std::string& nameSpace, uint32_t saveInterval = 60*60); + + void registerMetric(const std::string& shortName, const std::string& fullName); + + uint64_t getCounter(const std::string& shortName); // returns the actual value or 0 for unknown counters + + Incrementer generateMetricIncrementer(const std::string& shortName); + + + void saveData(); + + + const std::string& nameSpace; + + private: + + uint32_t saveInterval; // seconds + uint32_t tickInterval = 60; // seconds; internal tick task interval + + std::time_t lastSaved = std::time(NULL); // unix timestamp + + void tickTask(); + + std::map<std::string, CounterMetric*> counters; + + nvs_handle_t nvs; + + }; + + } +} diff --git a/CLC-qthing/device_config.h b/CLC-qthing/device_config.h index b9bf347..41978b1 100644 --- a/CLC-qthing/device_config.h +++ b/CLC-qthing/device_config.h @@ -1,5 +1,5 @@ // hostname and device namespace -#define DEVICE_NAME "CyanLight" +#define DEVICE_NAME "CLC" #define NTP_SERVER "pool.ntp.org" diff --git a/CLC-qthing/device_main.cpp b/CLC-qthing/device_main.cpp index fc83f73..755fce8 100644 --- a/CLC-qthing/device_main.cpp +++ b/CLC-qthing/device_main.cpp @@ -11,34 +11,40 @@ -CyanLight::CyanLightControl ctrl(1); +qthing::Config cfg; + +CyanLight::CyanLightControl ctrl(3); + void device_main() { - // ground the pin beneath our channel 0 IO - /* uint8_t GND = 23; + cfg.apply(); - gpio_config_t conf; + ctrl.setFrqRes(100, 19); - conf.intr_type = GPIO_INTR_DISABLE; - conf.mode = GPIO_MODE_OUTPUT; - conf.pin_bit_mask = 1ULL << GND; - conf.pull_up_en = GPIO_PULLUP_DISABLE; - conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_config(&conf); - gpio_set_level((gpio_num_t)GND, 0); */ + for (uint8_t i = 0; i < 100; i++) { + bool _f = i % 2 == 0; - qthing::Config cfg; - cfg.apply(); + ctrl.setPWM(0, _f * 1.0f); + ctrl.setPWM(2, (_f ^ 1) * 1.0f); + vTaskDelay(50 / portTICK_PERIOD_MS); + } - qthing::enable_wifi(); + ctrl.setPWM(0, 0.0f); + ctrl.setPWM(1, 0.0f); + ctrl.setPWM(2, 1.0f); + + + qthing::enable_wifi(); return; + + auto delay = 10 / portTICK_PERIOD_MS; float limit = 50.0f; -- GitLab