From a481419c3b7299c9fe822c1ff122191bc91e973e Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Mon, 22 Nov 2021 00:13:29 +0100
Subject: [PATCH] =?UTF-8?q?This=20steaming=20stockpile=20of=20=F0=9F=92=A9?=
 =?UTF-8?q?=20compiles=20now=E2=80=A6=20MQTT=20API=20also=20almost=20finis?=
 =?UTF-8?q?hed;=20Everything=20implemented=20MQTT-Endpoint=20tested=20and?=
 =?UTF-8?q?=20working=20flawlessly=20=F0=9F=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CLC-qthing/Controller.cpp       | 120 ++++++++++++++++++++++++++++++--
 CLC-qthing/CyanLightControl.hpp |  13 ++--
 CLC-qthing/IRSender.cpp         |   2 +
 CLC-qthing/IRSender.hpp         |   2 +
 CLC-qthing/PWMChannel.cpp       |  11 ++-
 CLC-qthing/PWMChannel.hpp       |   5 +-
 CLC-qthing/device_main.cpp      |  65 +----------------
 CLC-qthing/floatOut.py          |  16 +++++
 8 files changed, 156 insertions(+), 78 deletions(-)
 create mode 100755 CLC-qthing/floatOut.py

diff --git a/CLC-qthing/Controller.cpp b/CLC-qthing/Controller.cpp
index 3b032e1..bbcbb4a 100644
--- a/CLC-qthing/Controller.cpp
+++ b/CLC-qthing/Controller.cpp
@@ -1,16 +1,38 @@
 #include "CyanLightControl.hpp"
 
+#include "qthing.h"
+#include "mqtt_common.h"
+
+#include <string>
+#include <cstdio>
+#include <cstdlib>
 #include <algorithm>
 
 #include "esp_err.h"
+#include "esp_log.h"
 #include "driver/ledc.h"
 
 
 
+const char *TAG = "CLC";
+const std::string delimiter = ":";
+
+
+float CyanLight::bytes2float(uint8_t *bytes) {
+  float f;
+
+  memcpy(&f, bytes, sizeof(f));
+
+  return f;
+}
+
+
 CyanLight::Controller::Controller(uint8_t networkChannel, uint8_t channelsConfigured) : networkChannel{networkChannel} {
 
   this->channelsConfigured = std::max(channelsConfigured, CyanLight::MAX_CHANNELS);
 
+  this->channels = new CyanLight::PWMChannel*[this->channelsConfigured];
+  //this->channels = (CyanLight::PWMChannel **) malloc(this->channelsConfigured * sizeof(CyanLight::PWMChannel*));
 
   this->timer_cfg.duty_resolution = (ledc_timer_bit_t)this->resolution;
   this->timer_cfg.freq_hz = this->frequency;
@@ -25,29 +47,117 @@ CyanLight::Controller::Controller(uint8_t networkChannel, uint8_t channelsConfig
 
   for (uint8_t i = 0; i < channelsConfigured; i++) {
     this->channels[i] = new CyanLight::PWMChannel(i, CyanLight::channelGPIOS[i]);
+
+    char topic[256];
+    snprintf(topic, sizeof(topic), DEVICE_NAMESPACE "CyanLight/pwm/$%i", i);
+
+    add_message_callback(topic, [&, i](std::string message) {
+
+      this->setChannel(i, strtof(message.c_str(), NULL));
+
+      // float f = strtof(message.c_str(), NULL);
+      // ESP_LOGW(TAG, "i: %d   msg: %s   f: %f", i, message.c_str(), f);
+    });
   }
+
+
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/frequency/set", [&](std::string message) {
+    long int frq = strtol(message.c_str(), NULL, 0);
+    this->setFrequency(frq);
+  });
+
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/resolution/set", [&](std::string message) {
+    long int res = strtol(message.c_str(), NULL, 0);
+    this->setResolution(res);
+  });
+
+  // atomic setter for both values
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/frqres/set", [&](std::string message) {
+    std::string::size_type found = message.find(delimiter);
+
+    if (found == std::string::npos) {
+      ESP_LOGW("CLC", "Invalid message format[ '%s' ]", message.c_str());
+      return;
+    }
+
+    std::string _frq = message.substr(0, found);
+    std::string _res = message.substr(found + delimiter.length());
+
+    long int frq = strtol(_frq.c_str(), NULL, 0);
+    long int res = strtol(_res.c_str(), NULL, 0);
+
+    if (frq == 0 || res == 0) {
+      ESP_LOGW("CLC", "Invalid message format[ '%s' ]", message.c_str());
+      return;
+    }
+
+    this->setFrqRes(frq, res);
+  });
+
+
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/frequency/get", [&](std::string ignored) {
+    char tmp[16];
+    snprintf(tmp, sizeof(tmp), "%i", this->getFrequency());
+    publish_message(DEVICE_NAMESPACE "CyanLight/frequency", tmp);
+  });
+
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/resolution/get", [&](std::string ignored) {
+    char tmp[16];
+    snprintf(tmp, sizeof(tmp), "%i", this->getResolution());
+    publish_message(DEVICE_NAMESPACE "CyanLight/resolution", tmp);
+  });
+
+  // and for symmetric reasons: here comes the counterpart to the atomic frq-res-setter
+  add_message_callback(DEVICE_NAMESPACE "CyanLight/frqres/get", [&](std::string ignored) {
+    char tmp[32];
+    snprintf(tmp, sizeof(tmp), "%i%s%i", this->getFrequency(), delimiter.c_str(), this->getResolution());
+    publish_message(DEVICE_NAMESPACE "CyanLight/frqres", tmp);
+  });
 }
 
 
-bool CyanLight::Controller::setFrqRes(uint8_t frq_hz, uint8_t res_bits) {
-  this->timer_cfg.duty_resolution = (ledc_timer_bit_t)this->resolution;
-  this->timer_cfg.freq_hz = this->frequency;
+void CyanLight::Controller::setChannel(uint8_t channel, float value) {
+
+  if (channel >= this->channelsConfigured) {
+    ESP_LOGW(TAG, "ChannelID out of range: channel[ %i ]", channel);
+    return;
+  }
+
+  if (value < 0.0f) value = 0.0f;
+  if (value > 1.0f) value = 1.0f;
+
+  uint32_t maxPWM = 1 << (this->resolution - 1);
+  uint32_t pwm = (uint32_t)( value * (maxPWM - 1) );
+
+  this->channels[channel]->setPWM(pwm);
+}
+
+
+bool CyanLight::Controller::setFrqRes(uint32_t frq_hz, uint8_t res_bits) {
+
+  this->timer_cfg.duty_resolution = (ledc_timer_bit_t)res_bits;
+  this->timer_cfg.freq_hz = frq_hz;
 
   if (ledc_timer_config(&this->timer_cfg) == ESP_OK) {
     this->frequency = frq_hz;
     this->resolution = res_bits;
 
+    ESP_LOGI(TAG, "frequency[ %i Hz ]  resolution[ %i bit ]", frq_hz, res_bits);
+
     return true;
+
   } else {
+
+    ESP_LOGW(TAG, "Invalid frequency[ %i Hz ] and resolution[ %i bit ] setting!", frq_hz, res_bits);
     return false;
   }
 }
 
-bool CyanLight::Controller::setFrequency(uint16_t frq_hz) {
+bool CyanLight::Controller::setFrequency(uint32_t frq_hz) {
   return this->setFrqRes(frq_hz, this->resolution);
 }
 
-uint16_t CyanLight::Controller::getFrequency() {
+uint32_t CyanLight::Controller::getFrequency() {
   return this->frequency;
 }
 
diff --git a/CLC-qthing/CyanLightControl.hpp b/CLC-qthing/CyanLightControl.hpp
index 135ce71..2a45baa 100644
--- a/CLC-qthing/CyanLightControl.hpp
+++ b/CLC-qthing/CyanLightControl.hpp
@@ -19,22 +19,25 @@ namespace CyanLight {
     public:
       Controller(uint8_t networkChannel, uint8_t channelsConfigured = 1);
 
-      bool setFrequency(uint16_t frq_hz);
-      uint16_t getFrequency();
+      void setChannel(uint8_t channel, float value);
+
+      bool setFrequency(uint32_t frq_hz);
+      uint32_t getFrequency();
 
       bool setResolution(uint8_t res_bits);
       uint8_t getResolution();
 
-      bool setFrqRes(uint16_t frq_hz, uint8_t res_bits);
+      bool setFrqRes(uint32_t frq_hz, uint8_t res_bits);
     private:
-      uint16_t frequency = 1000;  // Hz
+      uint32_t frequency = 1000;  // Hz
       uint8_t resolution =  10;  // bits
 
       uint8_t networkChannel;
       uint8_t channelsConfigured;
-      PWMChannel channels[MAX_CHANNELS];
+      PWMChannel **channels;
 
       ledc_timer_config_t timer_cfg;
   };
 
+  float bytes2float(uint8_t *bytes);
 }
diff --git a/CLC-qthing/IRSender.cpp b/CLC-qthing/IRSender.cpp
index c4965f8..86f3e98 100644
--- a/CLC-qthing/IRSender.cpp
+++ b/CLC-qthing/IRSender.cpp
@@ -1,5 +1,7 @@
 #include "IRSender.hpp"
 
+#include <string>
+
 #include "driver/gpio.h"
 #include "driver/ledc.h"
 
diff --git a/CLC-qthing/IRSender.hpp b/CLC-qthing/IRSender.hpp
index 8b5d703..b97ed7f 100644
--- a/CLC-qthing/IRSender.hpp
+++ b/CLC-qthing/IRSender.hpp
@@ -1,5 +1,7 @@
 #include <cinttypes>
 
+#include <string>
+
 
 class IRSender {
   public:
diff --git a/CLC-qthing/PWMChannel.cpp b/CLC-qthing/PWMChannel.cpp
index e949af6..8e91ba9 100644
--- a/CLC-qthing/PWMChannel.cpp
+++ b/CLC-qthing/PWMChannel.cpp
@@ -29,11 +29,16 @@ CyanLight::PWMChannel::PWMChannel(uint8_t channel, uint8_t gpio) : channel{(ledc
 
   ledc_channel_config(&ledc_channel);
 
-  setBrightness(0);
+  setPWM(0);
 }
 
-void CyanLight::PWMChannel::setBrightness(uint32_t pwm) {
-
+void CyanLight::PWMChannel::setPWM(uint32_t pwm) {
   ledc_set_duty(LEDC_HIGH_SPEED_MODE, this->channel, pwm);
   ledc_update_duty(LEDC_HIGH_SPEED_MODE, this->channel);
+
+  this->pwm = pwm;
+}
+
+uint32_t CyanLight::PWMChannel::getPWM() {
+  return this->pwm;
 }
diff --git a/CLC-qthing/PWMChannel.hpp b/CLC-qthing/PWMChannel.hpp
index 20cea41..125c7d0 100644
--- a/CLC-qthing/PWMChannel.hpp
+++ b/CLC-qthing/PWMChannel.hpp
@@ -11,10 +11,11 @@ namespace CyanLight {
     public:
       PWMChannel(uint8_t channel, uint8_t gpio);
 
-      uint32_t getBrightness();
-      void setBrightness(uint32_t pwm);
+      uint32_t getPWM();
+      void setPWM(uint32_t pwm);
     
     private:
+      uint32_t pwm = 0;
       ledc_channel_t channel;
   };
 
diff --git a/CLC-qthing/device_main.cpp b/CLC-qthing/device_main.cpp
index ffa9520..e4eeb51 100644
--- a/CLC-qthing/device_main.cpp
+++ b/CLC-qthing/device_main.cpp
@@ -1,64 +1,12 @@
 #include <qthing.h>
 
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-
 #include "driver/gpio.h"
 
-#include "mqtt_common.h"
-#include "esp_log.h"
-
-
-#include "IRSender.hpp"
-
-#include "Arduino.h"
-
-
-// #######################
-// ####### CONFIG ########
-// #######################
-
-const uint8_t senderTX = 26;
-const uint8_t senderCLK = 25;
-
-const uint8_t receiverRX = 23;
-
-// ### end cfg ###
-
-
-HardwareSerial sender(1);
-HardwareSerial receiver(2);
+#include "CyanLightControl.hpp"
 
 
-void senderTask(void *ignored) {
 
-  uint16_t delay = 10;
-  vTaskDelay(delay / portTICK_PERIOD_MS);
-
-  while (true) {
-    sender.print("Hello, Infrared communication!");
-    vTaskDelay(delay / portTICK_PERIOD_MS);
-
-    sender.print(" typing…");
-    vTaskDelay(delay / portTICK_PERIOD_MS);
-
-    sender.print(" 🐾…");
-    vTaskDelay(delay / portTICK_PERIOD_MS);
-
-    sender.println(" 🕷🕸😏");
-    vTaskDelay(delay / portTICK_PERIOD_MS);
-  }
-}
-
-
-void receiverTask(void *ignored) {
-  while (true) {
-    if (receiver.available())
-      Serial.print( (char)receiver.read() );
-    else
-      vTaskDelay(2);
-  }
-}
+CyanLight::Controller ctrl(0, 3);
 
 
 void device_main() {
@@ -80,15 +28,6 @@ void device_main() {
 
 
 
-  // IRSender(senderTX, senderCLK);
-  // TODO: configure UART in IRSender!
-
-
-  // sender.begin(baud, SERIAL_8N1, -1, senderTX);  // tx = 27
-  // receiver.begin(baud, SERIAL_8N1, receiverRX, -1);  // rx = 26
-
-  // xTaskCreate(senderTask, "sender", 8192, NULL, 6, NULL);
-  // xTaskCreate(receiverTask, "receiver", 8192, NULL, 6, NULL);
 
 
   enable_wlan();
diff --git a/CLC-qthing/floatOut.py b/CLC-qthing/floatOut.py
new file mode 100755
index 0000000..96cd796
--- /dev/null
+++ b/CLC-qthing/floatOut.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i python -p python3
+
+import struct
+
+
+value = 13.37
+
+
+def f2b(f):
+  return bytearray(struct.pack("f", f))
+
+
+ba = f2b(value)
+print(ba)
+print([ "0x%02x" % b for b in ba ])
-- 
GitLab