From 071c792cdf9a7f318dd9902709531eae605f03a5 Mon Sep 17 00:00:00 2001
From: Jan Grewe <jan@faked.org>
Date: Sat, 4 Nov 2023 02:43:12 +0100
Subject: [PATCH] add automatic pH balancing

---
 growbox.yaml                 |  1 +
 packages/base.yaml           | 19 ++++++++++++
 packages/dosing.yaml         | 56 ++++++++++++++++++++++++++++++++++++
 packages/fan_power.yaml      |  5 ++++
 packages/light_power.yaml    |  5 ++++
 packages/light_settings.yaml |  4 +--
 packages/pca9685.yaml        | 10 +++++--
 packages/secrets.yaml.dist   |  4 +--
 packages/time_schedule.yaml  | 16 +++--------
 9 files changed, 102 insertions(+), 18 deletions(-)
 create mode 100644 packages/dosing.yaml

diff --git a/growbox.yaml b/growbox.yaml
index 6661bde..f239ddd 100644
--- a/growbox.yaml
+++ b/growbox.yaml
@@ -28,3 +28,4 @@ packages:
   ph:             !include packages/ph.yaml
   sts35:          !include packages/sts35.yaml
   pca9685:        !include packages/pca9685.yaml
+  dosing:         !include packages/dosing.yaml
diff --git a/packages/base.yaml b/packages/base.yaml
index 518550c..7510f2c 100644
--- a/packages/base.yaml
+++ b/packages/base.yaml
@@ -51,6 +51,9 @@ prometheus:
       id: uptime
       name: Uptime
 
+debug:
+  update_interval: 5s
+
 sensor:
   - platform: wifi_signal
     id: rssi
@@ -62,11 +65,27 @@ sensor:
     update_interval: 15s
     internal: true
 
+  # - platform: debug
+  #   free:
+  #     name: "Device: Heap Free"
+  #   block:
+  #     name: "Device: Heap Max Block"
+  #   loop_time:
+  #     name: "Device: Loop Time"
+  #   psram:
+  #     name: "Device: Free PSRAM"
+
 text_sensor:
   - platform: version
     name: "ESPHome Version"
     hide_timestamp: true
 
+  - platform: debug
+    #device:
+    #  name: "Device: Info"
+    reset_reason:
+      name: "Device: Reset Reason"
+
   - platform: template
     id: device_uptime
     name: "Device: Uptime"
diff --git a/packages/dosing.yaml b/packages/dosing.yaml
new file mode 100644
index 0000000..aba9dbe
--- /dev/null
+++ b/packages/dosing.yaml
@@ -0,0 +1,56 @@
+switch:
+  - platform: template
+    id: ph_dosing_enabled
+    name: "pH Dosing"
+    optimistic: true
+    restore_mode: RESTORE_DEFAULT_OFF
+
+select:
+  - platform: template
+    id: ph_dosing_target
+    name: "pH Dosing: Target Value"
+    options: ["5.0", "5.1", "5.2", "5.3", "5.4", "5.5", "5.6", "5.7", "5.8", "5.9", "6.0", "6.1", "6.2", "6.3", "6.4", "6.5"]
+    initial_option: "5.8"
+    optimistic: true
+    restore_value: true
+  - platform: template
+    id: ph_dosing_min
+    name: "pH Dosing: Min. Value"
+    options: ["5.0", "5.1", "5.2", "5.3", "5.4", "5.5", "5.6", "5.7", "5.8", "5.9", "6.0"]
+    initial_option: "5.5"
+    optimistic: true
+    restore_value: true
+  - platform: template
+    id: ph_dosing_max
+    name: "pH Dosing: Max. Value"
+    options: ["5.5", "5.6", "5.7", "5.8", "5.9", "6.0", "6.1", "6.2", "6.3", "6.4", "6.5"]
+    initial_option: "6.0"
+    optimistic: true
+    restore_value: true
+
+interval:
+  - interval: 15min
+    then:
+      - script.execute: ph_dosing
+
+script:
+  - id: ph_dosing
+    then:
+      - lambda: |-
+          if (id(ph_dosing_enabled).state)
+          {
+            if (id(ph).state <= atof(id(ph_dosing_min).state.c_str()))
+            {
+              ESP_LOGI("dosing", "pH value too low (%.2f <= %.2f)", id(ph).state, atof(id(ph_dosing_min).state.c_str()));
+              id(ph_up).turn_on();
+            }
+            else if (id(ph).state >= atof(id(ph_dosing_max).state.c_str()))
+            {
+              ESP_LOGI("dosing", "pH value too high (%.2f >= %.2f)", id(ph).state, atof(id(ph_dosing_max).state.c_str()));
+              id(ph_down).turn_on();
+            }
+            else 
+            {
+              ESP_LOGI("dosing", "pH value within range (%.2f <= %.2f <= %.2f)", atof(id(ph_dosing_min).state.c_str()), id(ph).state, atof(id(ph_dosing_max).state.c_str()));
+            }
+          }
diff --git a/packages/fan_power.yaml b/packages/fan_power.yaml
index 24d00f0..1bd411d 100644
--- a/packages/fan_power.yaml
+++ b/packages/fan_power.yaml
@@ -17,6 +17,11 @@ switch:
     turn_off_action:
       - http_request.post: http://${hostname_fan}/switch/power/turn_off
 
+interval:
+  - interval: 1min
+    then:
+      - script.execute: fan_power_state
+
 script:
   - id: fan_power_state
     then: 
diff --git a/packages/light_power.yaml b/packages/light_power.yaml
index 62db1d4..716f51d 100644
--- a/packages/light_power.yaml
+++ b/packages/light_power.yaml
@@ -17,6 +17,11 @@ switch:
     turn_off_action:
       - http_request.post: http://${hostname_light}/switch/power/turn_off
 
+interval:
+  - interval: 1min
+    then:
+      - script.execute: light_power_state
+
 script:
   - id: light_power_state
     then:
diff --git a/packages/light_settings.yaml b/packages/light_settings.yaml
index 059dffb..439b7dc 100644
--- a/packages/light_settings.yaml
+++ b/packages/light_settings.yaml
@@ -9,12 +9,12 @@ sensor:
   - platform: template
     id: light_schedule
     name: "Light Schedule"
-    lambda: return id(schedule).active_index();
+    lambda: return id(select_light_schedule).active_index();
     internal: true
 
 select:
   - platform: template
-    id: schedule
+    id: select_light_schedule
     name: "Light: Schedule"
     options: ["Disabled", "Grow", "Bloom"]
     initial_option: "Disabled"
diff --git a/packages/pca9685.yaml b/packages/pca9685.yaml
index 08df1a3..8567875 100644
--- a/packages/pca9685.yaml
+++ b/packages/pca9685.yaml
@@ -42,7 +42,10 @@ switch:
         - switch.turn_off: ph_down
     on_turn_off:
       - then:
-        - logger.log: "Stopped dosing 'pH Down'"
+        - logger.log:
+            level: INFO
+            tag: "dosing"
+            format: "Stopped dosing 'pH Down'"
   - platform: output
     output: output_ph_up
     id: ph_up
@@ -58,4 +61,7 @@ switch:
         - switch.turn_off: ph_up
     on_turn_off:
       - then:
-        - logger.log: "Stopped dosing 'pH Up'"
+        - logger.log:
+            level: INFO
+            tag: "dosing"
+            format: "Stopped dosing 'pH Up'"
diff --git a/packages/secrets.yaml.dist b/packages/secrets.yaml.dist
index a537f16..d2dd5b8 100644
--- a/packages/secrets.yaml.dist
+++ b/packages/secrets.yaml.dist
@@ -5,6 +5,6 @@ api_password: ""
 domain: "local"
 timezone: "Europe/Berlin"
 pump1_ml_sec: "2.15"    # millilitre per second
-pump1_dose_ml: "10"     # millilitre per dose
+pump1_dose_ml: "2"      # millilitre per dose
 pump2_ml_sec: "2.15"    # millilitre per second
-pump2_dose_ml: "10"     # millilitre per dose
+pump2_dose_ml: "5"      # millilitre per dose
diff --git a/packages/time_schedule.yaml b/packages/time_schedule.yaml
index 6f287d1..fb93757 100644
--- a/packages/time_schedule.yaml
+++ b/packages/time_schedule.yaml
@@ -7,32 +7,24 @@ time:
       - cron: ${schedule_grow_on}
         then:
           - lambda: |-
-              if (id(schedule).state == "Grow") {
+              if (id(select_light_schedule).state == "Grow") {
                 id(power_light).turn_on();
               }
       - cron: ${schedule_grow_off}
         then:
           - lambda: |-
-              if (id(schedule).state == "Grow") {
+              if (id(select_light_schedule).state == "Grow") {
                 id(power_light).turn_off();
               }
       - cron: ${schedule_bloom_on}
         then:
           - lambda: |-
-              if (id(schedule).state == "Bloom") {
+              if (id(select_light_schedule).state == "Bloom") {
                 id(power_light).turn_on();
               }
       - cron: ${schedule_bloom_off}
         then:
           - lambda: |-
-              if (id(schedule).state == "Bloom") {
+              if (id(select_light_schedule).state == "Bloom") {
                 id(power_light).turn_off();
               }
-      - seconds: 0
-        minutes: /1
-        then:
-          - script.execute: light_power_state
-      - seconds: 0
-        minutes: /1
-        then:
-          - script.execute: fan_power_state
-- 
GitLab