From 16c25d88bb5b80c5cf36e4c30abef19ea60d59ef Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 17:15:52 -0500
Subject: [PATCH 01/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 52 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 008c959..f5c273d 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -188,6 +188,26 @@ sensor:
     update_interval: "${update_ph}"
     state_class: "measurement"
     device_class: PH
+    on_custom: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x); 
 
   # EZO Circuit - EC
   # Conductivity
@@ -203,7 +223,23 @@ sensor:
     on_custom: 
       then:
         - lambda: 
-            id(raw_value_ec).publish_state(x);
+            id(result_ec).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
 
   # Specific Gravity
   - platform: copy 
@@ -554,11 +590,17 @@ text_sensor:
         return {"Unknown"};
       }
 
-  # Conductivity Raw Value
+  # Selected Command Result - pH
+  - platform: template
+    name: pH - Command Result
+    id: result_ph
+    # disabled_by_default: true
+    entity_category: "Config"
+
+  # Selected Command Result - Conductivity
   - platform: template
-    name: EC - Raw Value
-    id: raw_value_ec
-    update_interval: never
+    name: EC - Command Result
+    id: result_ec
     # disabled_by_default: true
     entity_category: "Config"
 

From 47ed1df5797513a98202e8d42ab36e26c401fb7c Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 19:42:49 -0500
Subject: [PATCH 02/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 336 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 310 insertions(+), 26 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 830e5c9..b105e92 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -3,7 +3,7 @@ substitutions:
   name: "aquapi"
   friendly_name: "AquaPi"
   # App Version - Updated: 8/2023
-  app_version: "1.2.4"
+  app_version: "1.3"
   # Import Config
   import_config: "false"
   # Logger Level
@@ -77,6 +77,7 @@ esphome:
     priority: 200
     then:
       - component.update: water_level
+      - button.press: read_ec
 
 esp32:
   board: esp32dev
@@ -207,14 +208,13 @@ sensor:
     on_t: 
       then:
         - lambda: 
-
-            id(result_ph).publish_state(x);     
+            id(result_ph).publish_state(x); 
 
   # EZO Circuit - EC
-  # Conductivity
+  # Conductivity Probe
   - platform: ezo
     icon: mdi:shaker-outline
-    name: "Salinity"
+    # name: "Salinity"
     id: ec_ezo
     address: ${addEC}
     unit_of_measurement: "ppt"
@@ -224,7 +224,7 @@ sensor:
     on_custom: 
       then:
         - lambda: 
-            id(result_ec).publish_state(x);
+            id(raw_value_ec).publish_state(x);
     on_calibration: 
       then:
         - lambda: 
@@ -242,29 +242,109 @@ sensor:
         - lambda: 
             id(result_ec).publish_state(x);
 
-  # Specific Gravity
-  - platform: copy 
-    source_id: ec_ezo
+  # Conductivity
+  - platform: template
+    name: Conductivity
+    id: sensor_conductivity
+    icon: mdi:lightning-bolt-outline
+    unit_of_measurement: "uS/cm"
+    accuracy_decimals: 0
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[0]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # TDS
+  - platform: template
+    name: TDS
+    id: sensor_tds
+    unit_of_measurement: "mg/l"
+    icon: mdi:water-opacity
+    accuracy_decimals: 0
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[1]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # Salinity
+  - platform: template
+    name: Salinity
+    id: sensor_salinity
     icon: mdi:shaker-outline
-    name: "Specific Gravity"
-    filters:
-      - lambda: return x;
-    unit_of_measurement: ""
-    accuracy_decimals: 3
+    unit_of_measurement: "ppt"
+    accuracy_decimals: 2
+    update_interval: "${update_ec}"
     state_class: "measurement"
-    disabled_by_default: true
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[2]);
+      } 
+      else {
+        return NULL;
+      }
 
-  # Conductivity
-  - platform: copy 
-    source_id: ec_ezo
-    name: "Conductivity"
-    icon: mdi:flash
-    filters:
-      - lambda: return x;
-    unit_of_measurement: "μS/cm"
+  # Specific Gravity
+  - platform: template
+    name: Specific Gravity
+    id: sensor_specific_gravity
+    icon: mdi:cup-water
+    unit_of_measurement: ""
     accuracy_decimals: 3
+    update_interval: "${update_ec}"
     state_class: "measurement"
-    disabled_by_default: true
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[3]);
+      } 
+      else {
+        return NULL;
+      }
 
   # EZO Circuit - RTD
   # Temperature
@@ -591,16 +671,29 @@ text_sensor:
         return {"Unknown"};
       }
 
+  # Conductivity Raw Value
+  - platform: template
+    # name: EC - Raw Value
+    id: raw_value_ec
+    # disabled_by_default: true
+    entity_category: "Config"
+    on_value: 
+      then:
+        - component.update: sensor_salinity
+        - component.update: sensor_conductivity
+        - component.update: sensor_tds
+        - component.update: sensor_specific_gravity
+
   # Selected Command Result - pH
   - platform: template
-    name: pH - Command Result
+    # name: pH - Command Result
     id: result_ph
     # disabled_by_default: true
     entity_category: "Config"
 
   # Selected Command Result - Conductivity
   - platform: template
-    name: EC - Command Result
+    # name: EC - Command Result
     id: result_ec
     # disabled_by_default: true
     entity_category: "Config"
@@ -670,6 +763,142 @@ button:
     entity_category: "Config"
     disabled_by_default: true
 
+  # Read pH Probe
+  - platform: template
+    name: pH - Read
+    id: read_ph
+    entity_category: "Config"
+    # disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(ph_ezo).send_custom("R");
+
+  # Read Conductivity Probe
+  - platform: template
+    name: EC - Read
+    id: read_ec
+    entity_category: "Config"
+    # disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(ec_ezo).send_custom("R");
+
+  # Send Selected EZO Command - pH
+  - platform: template
+    name: pH - Command Send Selected
+    id: send_selected_ph
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_ph).state == "Read") {
+              id(ph_ezo).send_custom("R");
+            }
+            // Get Device Firmware Version
+            if (id(select_command_ph).state == "Information") {
+              id(ph_ezo).get_device_information();
+            }
+            if (id(select_command_ph).state == "Status") {
+              id(ph_ezo).send_custom("Status");
+            }
+            if (id(select_command_ph).state == "Get Slope") {
+              id(ph_ezo).get_slope();
+            }
+            if (id(select_command_ph).state == "Check Calibration") {
+              id(ph_ezo).get_calibration();
+            }  
+            if (id(select_command_ph).state == "Calibrate @ MID  = 7  (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_mid(7.00);
+            }
+            if (id(select_command_ph).state == "Calibrate @ LOW  = 4  (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_low(4.00);
+            }
+            if (id(select_command_ph).state == "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_high(10.00);
+            }
+            if (id(select_command_ph).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
+              id(ph_ezo).clear_calibration();
+            }
+
+  # Send Selected EZO Command - Conductitivy
+  - platform: template
+    name: EC - Command Send Selected
+    id: send_selected_ec
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_ec).state == "Read") {
+              id(ec_ezo).send_custom("R");
+            }
+            if (id(select_command_ec).state == "Information") {
+              id(ec_ezo).get_device_information();
+            }
+            if (id(select_command_ec).state == "Status") {
+              id(ec_ezo).send_custom("Status");
+            }
+            if (id(select_command_ec).state == "Get Probe K Value") {
+              id(ec_ezo).send_custom("K,?");
+            }  
+            if (id(select_command_ec).state == "Get TDS Value") {
+              id(ec_ezo).send_custom("TDS,?");
+            }  
+            if (id(select_command_ec).state == "Get Enabled Parameter(s)") {
+              id(ec_ezo).send_custom("O,?");
+            }  
+            if (id(select_command_ec).state == "Set Probe Type K1") {
+              id(ec_ezo).send_custom("K,1");
+            }
+            if (id(select_command_ec).state == "Output Units - All (Default)") {
+              id(ec_ezo).send_custom("O,EC,1");
+              id(ec_ezo).send_custom("O,TDS,1");
+              id(ec_ezo).send_custom("O,S,1");
+              id(ec_ezo).send_custom("O,SG,1");
+            }
+            if (id(select_command_ec).state == "Output Units - Conductivity") {
+              id(ec_ezo).send_custom("O,EC,1");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Salinity") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,1");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Output Units - Specific Gravity") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,1");
+            }
+            if (id(select_command_ec).state == "Output Units - TDS") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,1");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Check Calibration") {
+              id(ec_ezo).get_calibration();
+            }  
+            if (id(select_command_ec).state == "Calibrate @ 0 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_mid(7.00);
+            }
+            if (id(select_command_ec).state == "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_low(4.00);
+            }
+            if (id(select_command_ec).state == "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_high(10.00);
+            }
+            if (id(select_command_ec).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
+              id(ec_ezo).clear_calibration();
+            }
+
 number:
   # Temperature when Cool
   - platform: template
@@ -706,3 +935,58 @@ number:
       then:
         - component.update: temp_range
         - component.update: temp_range_2
+
+select:
+  - platform: template
+    name: pH - Command Select
+    id: select_command_ph
+    optimistic: true
+    disabled_by_default: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Slope"
+      - "Check Calibration"
+      - "Calibrate @ MID = 7 (WILL RESET CALIBRATION)"
+      - "Calibrate @ LOW = 4 (WILL RESET CALIBRATION)"
+      - "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)"
+      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
+    initial_option: "Read"
+    restore_value: true
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
+
+  - platform: template
+    name: EC - Command Select
+    id: select_command_ec
+    disabled_by_default: true
+    optimistic: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Probe K Value"
+      - "Get TDS Value"
+      - "Get Enabled Parameter(s)"
+      - "Set Probe Type K1"
+      - "Output Units - All (Default)"
+      - "Output Units - Conductivity"
+      - "Output Units - Salinity"
+      - "Output Units - Specific Gravity"
+      - "Output Units - TDS"
+      - "Check Calibration"
+      - "Calibrate @ 0 (WILL RESET CALIBRATION)"
+      - "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)"
+      - "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)"
+      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
+    initial_option: "Read"
+    restore_value: true
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
\ No newline at end of file

From 7c9a833f366aeac67bd53955851ded05fe6b4e1a Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 19:48:17 -0500
Subject: [PATCH 03/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index b105e92..03ab40d 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -673,7 +673,7 @@ text_sensor:
 
   # Conductivity Raw Value
   - platform: template
-    # name: EC - Raw Value
+    name: EC - Raw Value
     id: raw_value_ec
     # disabled_by_default: true
     entity_category: "Config"
@@ -686,14 +686,14 @@ text_sensor:
 
   # Selected Command Result - pH
   - platform: template
-    # name: pH - Command Result
+    name: pH - Command Result
     id: result_ph
     # disabled_by_default: true
     entity_category: "Config"
 
   # Selected Command Result - Conductivity
   - platform: template
-    # name: EC - Command Result
+    name: EC - Command Result
     id: result_ec
     # disabled_by_default: true
     entity_category: "Config"

From b2bd273dea245f57ce1e2cb682e4d2e9bfc9ae09 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 19:50:08 -0500
Subject: [PATCH 04/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 03ab40d..51c4c86 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -675,7 +675,7 @@ text_sensor:
   - platform: template
     name: EC - Raw Value
     id: raw_value_ec
-    # disabled_by_default: true
+    disabled_by_default: true
     entity_category: "Config"
     on_value: 
       then:
@@ -688,14 +688,14 @@ text_sensor:
   - platform: template
     name: pH - Command Result
     id: result_ph
-    # disabled_by_default: true
+    disabled_by_default: true
     entity_category: "Config"
 
   # Selected Command Result - Conductivity
   - platform: template
     name: EC - Command Result
     id: result_ec
-    # disabled_by_default: true
+    disabled_by_default: true
     entity_category: "Config"
 
 button:

From c9b9f928a64df69cd7bd8d73ed01a8bf67858a45 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 19:53:09 -0500
Subject: [PATCH 05/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 51c4c86..2b58b60 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -676,7 +676,6 @@ text_sensor:
     name: EC - Raw Value
     id: raw_value_ec
     disabled_by_default: true
-    entity_category: "Config"
     on_value: 
       then:
         - component.update: sensor_salinity
@@ -689,14 +688,12 @@ text_sensor:
     name: pH - Command Result
     id: result_ph
     disabled_by_default: true
-    entity_category: "Config"
 
   # Selected Command Result - Conductivity
   - platform: template
     name: EC - Command Result
     id: result_ec
     disabled_by_default: true
-    entity_category: "Config"
 
 button:
   # Soft Restart

From efd5ee407965f79ea5ba0498222077ed5e4f3385 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 20:40:39 -0500
Subject: [PATCH 06/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 94 +++++++++++++++++++++++++---------------------
 1 file changed, 51 insertions(+), 43 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 2b58b60..1b458bd 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -78,6 +78,8 @@ esphome:
     then:
       - component.update: water_level
       - button.press: read_ec
+      - button.press: send_selected_ec
+      - button.press: send_selected_ph
 
 esp32:
   board: esp32dev
@@ -127,6 +129,12 @@ light:
 dallas:
   - pin: ${dallasPin}
     update_interval: "${update_temp}"
+
+interval:
+  # Update Raw EC
+  - interval: "${update_ec}"
+    then:
+      - button.press: read_ec
     
 sensor:
   # Internal Magnetic Sensor
@@ -272,7 +280,7 @@ sensor:
   - platform: template
     name: TDS
     id: sensor_tds
-    unit_of_measurement: "mg/l"
+    unit_of_measurement: "mg/L"
     icon: mdi:water-opacity
     accuracy_decimals: 0
     update_interval: "${update_ec}"
@@ -716,49 +724,49 @@ button:
     name: "Shutdown"
     disabled_by_default: true
 
-  # EC
-  # Output Parameters
-  # Output Salinity
-  - platform: template
-    name: "EC - Output - Salinity"
-    id: ec_sal
-    on_press:
-      then:
-        - lambda: |-
-            id(ec_ezo).send_custom("O,EC,0");
-            id(ec_ezo).send_custom("O,TDS,0");
-            id(ec_ezo).send_custom("O,S,1");
-            id(ec_ezo).send_custom("O,SG,0");
-    entity_category: "Config"
-    disabled_by_default: true
+  # # EC
+  # # Output Parameters
+  # # Output Salinity
+  # - platform: template
+  #   name: "EC - Output - Salinity"
+  #   id: ec_sal
+  #   on_press:
+  #     then:
+  #       - lambda: |-
+  #           id(ec_ezo).send_custom("O,EC,0");
+  #           id(ec_ezo).send_custom("O,TDS,0");
+  #           id(ec_ezo).send_custom("O,S,1");
+  #           id(ec_ezo).send_custom("O,SG,0");
+  #   entity_category: "Config"
+  #   disabled_by_default: true
             
-  # Output Specific Gravity
-  - platform: template
-    name: "EC - Output - Specific Gravity"
-    id: ec_sg
-    on_press:
-      then:
-        - lambda: |-
-            id(ec_ezo).send_custom("O,EC,0");
-            id(ec_ezo).send_custom("O,TDS,0");
-            id(ec_ezo).send_custom("O,S,0");
-            id(ec_ezo).send_custom("O,SG,1");
-    entity_category: "Config"
-    disabled_by_default: true
-
-  # Output Conductivity
-  - platform: template
-    name: "EC - Output - Conductivity"
-    id: ec_cond
-    on_press:
-      then:
-        - lambda: |-
-            id(ec_ezo).send_custom("O,EC,1");
-            id(ec_ezo).send_custom("O,TDS,0");
-            id(ec_ezo).send_custom("O,S,0");
-            id(ec_ezo).send_custom("O,SG,0");
-    entity_category: "Config"
-    disabled_by_default: true
+  # # Output Specific Gravity
+  # - platform: template
+  #   name: "EC - Output - Specific Gravity"
+  #   id: ec_sg
+  #   on_press:
+  #     then:
+  #       - lambda: |-
+  #           id(ec_ezo).send_custom("O,EC,0");
+  #           id(ec_ezo).send_custom("O,TDS,0");
+  #           id(ec_ezo).send_custom("O,S,0");
+  #           id(ec_ezo).send_custom("O,SG,1");
+  #   entity_category: "Config"
+  #   disabled_by_default: true
+
+  # # Output Conductivity
+  # - platform: template
+  #   name: "EC - Output - Conductivity"
+  #   id: ec_cond
+  #   on_press:
+  #     then:
+  #       - lambda: |-
+  #           id(ec_ezo).send_custom("O,EC,1");
+  #           id(ec_ezo).send_custom("O,TDS,0");
+  #           id(ec_ezo).send_custom("O,S,0");
+  #           id(ec_ezo).send_custom("O,SG,0");
+  #   entity_category: "Config"
+  #   disabled_by_default: true
 
   # Read pH Probe
   - platform: template

From f580b8f1d33f8d55f266c6fea62c13c4be3a44e5 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 20:46:58 -0500
Subject: [PATCH 07/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 1b458bd..b7f562f 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -773,7 +773,7 @@ button:
     name: pH - Read
     id: read_ph
     entity_category: "Config"
-    # disabled_by_default: true
+    disabled_by_default: true
     on_press:
       then:
         - lambda: |-
@@ -784,7 +784,7 @@ button:
     name: EC - Read
     id: read_ec
     entity_category: "Config"
-    # disabled_by_default: true
+    disabled_by_default: true
     on_press:
       then:
         - lambda: |-

From 7bf503f217a2ceb7b6ba08e5e25c3eb70dac4dc4 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 21:21:24 -0500
Subject: [PATCH 08/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index b7f562f..be23626 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -717,7 +717,7 @@ button:
   - platform: safe_mode
     name: "Restart in Safe Mode"
     id: restart_safe
-    disabled_by_default: false
+    disabled_by_default: true
 
   # Shutdown
   - platform: shutdown

From 93392bdd0d8ab456b4e3f10c1776bafb21214958 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sat, 18 Nov 2023 23:43:04 -0500
Subject: [PATCH 09/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index be23626..a3f065e 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -104,8 +104,6 @@ wifi:
 
 captive_portal:
 
-# web_server:
-
 # Sets up Bluetooth LE (Only on ESP32) to allow the user to provision wifi credentials to the device.
 esp32_improv:
   authorizer: none
@@ -708,7 +706,7 @@ button:
   - platform: restart
     name: "Restart"
 
-  # Facroty Reset
+  # Factory Reset
   - platform: factory_reset
     name: Factory Reset (USE WITH CAUTION)
     disabled_by_default: true
@@ -958,7 +956,7 @@ select:
       - "Calibrate @ LOW = 4 (WILL RESET CALIBRATION)"
       - "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)"
       - "Calibrate CLEAR (WILL RESET CALIBRATION)"
-    initial_option: "Read"
+    initial_option: "Check Calibration"
     restore_value: true
     set_action:
       - logger.log:
@@ -989,7 +987,7 @@ select:
       - "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)"
       - "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)"
       - "Calibrate CLEAR (WILL RESET CALIBRATION)"
-    initial_option: "Read"
+    initial_option: "Check Calibration"
     restore_value: true
     set_action:
       - logger.log:

From e817b9187f0029688562037838f6e1ec1844e30d Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 00:32:41 -0500
Subject: [PATCH 10/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index a3f065e..e0d54fc 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -394,7 +394,8 @@ sensor:
     device_class: "carbon_dioxide"
     disabled_by_default: true
 
-  # EZO Circuit - Dissolved Oxygen
+  # EZO Circuit - DO
+  # Dissolved Oxygen
   - platform: ezo
     icon: mdi:molecule
     name: "Dissolved Oxygen"
@@ -406,7 +407,8 @@ sensor:
     state_class: "measurement"
     disabled_by_default: true
 
-  # EZO Circuit - Pump
+  # EZO Circuit - pmp
+  # Pump
   - platform: ezo
     icon: mdi:pump
     name: "Pump"

From 78ae5ebf4edad68e9ff1e0514e6868169b067780 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 00:38:58 -0500
Subject: [PATCH 11/26] initial modular

---
 aquapi_config.yaml             | 946 +--------------------------------
 common/aquapi.yaml             |  19 +
 common/binary.yaml             |  87 +++
 common/device_base.yaml        | 144 +++++
 common/ezo_co2.yaml            |  41 ++
 common/ezo_do.yaml             |  40 ++
 common/ezo_ec.yaml             | 289 ++++++++++
 common/ezo_hum.yaml            |  41 ++
 common/ezo_ph.yaml             | 120 +++++
 common/ezo_pmp.yaml            |  40 ++
 common/ezo_rtd.yaml            |  41 ++
 common/temperature_dallas.yaml | 173 ++++++
 12 files changed, 1050 insertions(+), 931 deletions(-)
 create mode 100644 common/aquapi.yaml
 create mode 100644 common/binary.yaml
 create mode 100644 common/device_base.yaml
 create mode 100644 common/ezo_co2.yaml
 create mode 100644 common/ezo_do.yaml
 create mode 100644 common/ezo_ec.yaml
 create mode 100644 common/ezo_hum.yaml
 create mode 100644 common/ezo_ph.yaml
 create mode 100644 common/ezo_pmp.yaml
 create mode 100644 common/ezo_rtd.yaml
 create mode 100644 common/temperature_dallas.yaml

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index e0d54fc..e1b2193 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -4,6 +4,9 @@ substitutions:
   friendly_name: "AquaPi"
   # App Version - Updated: 8/2023
   app_version: "1.3"
+  # Comment
+  comment: "AquaPi ESP32 - Aquarium Controller & Monitor"  
+  
   # Import Config
   import_config: "false"
   # Logger Level
@@ -64,934 +67,15 @@ substitutions:
   # EZO CO2
   update_co2: "60s"
 
-esphome:
-  name: "${name}"
-  friendly_name: "${friendly_name}"
-  # Automatically add the mac address to the name
-  name_add_mac_suffix: true
-  comment: AquaPi ESP32 - Aquarium Controller & Monitor
-  project:
-    name: TheRealFalseReality.aquapi
-    version: "${app_version}"
-  on_boot: 
-    priority: 200
-    then:
-      - component.update: water_level
-      - button.press: read_ec
-      - button.press: send_selected_ec
-      - button.press: send_selected_ph
-
-esp32:
-  board: esp32dev
-  framework:
-    type: arduino
-
-# Enable logging
-logger:
-  level: "${logger}"
-
-# Enable Home Assistant API
-api:
-
-ota:
-
-dashboard_import:
-  package_import_url: github://TheRealFalseReality/aquapi/aquapi_config.yaml@main
-  import_full_config: ${import_config}
-
-wifi: 
-  ap:
-
-captive_portal:
-
-# Sets up Bluetooth LE (Only on ESP32) to allow the user to provision wifi credentials to the device.
-esp32_improv:
-  authorizer: none
-  
-improv_serial:
-
-# i2c Pins
-i2c:
-  sda: ${sdaPin}
-  scl: ${sclPin}
-  scan: true
-  id: bus_a
-
-# Internal Blue LED
-light:
-  - platform: status_led
-    pin: GPIO2
-    id: internal_led
-
-# 18B20 sensor Pin
-dallas:
-  - pin: ${dallasPin}
-    update_interval: "${update_temp}"
-
-interval:
-  # Update Raw EC
-  - interval: "${update_ec}"
-    then:
-      - button.press: read_ec
-    
-sensor:
-  # Internal Magnetic Sensor
-  - platform: esp32_hall
-    name: "ESP32 Hall Sensor"
-    entity_category: "diagnostic"
-
-  # Internal Temp.
-  - platform: internal_temperature
-    name: "Internal Temperature"
-
-  # Wifi Signal 
-  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
-    # name: "WiFi Signal dB"
-    id: wifi_signal_db
-    entity_category: "diagnostic"
-
-  # Wifi %
-  - platform: copy # Reports the WiFi signal strength in %
-    source_id: wifi_signal_db
-    name: "WiFi Signal Strength"
-    filters:
-      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
-    unit_of_measurement: "%"
-    entity_category: "diagnostic"
-
-  # Uptime sensor
-  - platform: uptime
-    name: Uptime
-
-  # of I2C devices connected
-  - platform: template
-    name: "I2C Devices Connected"
-    id: i2c_devices
-    icon: mdi:integrated-circuit-chip
-    entity_category: "diagnostic"
-    disabled_by_default: true
-    lambda: |-
-      byte error, address;
-      int nDevices;
-      nDevices = 0;
-      for(address = 1; address < 127; address++) {
-        Wire.beginTransmission(address);
-        error = Wire.endTransmission();
-        if (error == 0) {
-          nDevices++;
-        }
-      }
-      return nDevices;
-
-  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
-  # EZO Circuit - pH
-  - platform: ezo
-    icon: mdi:ph
-    name: "pH"
-    id: ph_ezo
-    address: ${addPH}
-    unit_of_measurement: ""
-    accuracy_decimals: 2
-    update_interval: "${update_ph}"
-    state_class: "measurement"
-    device_class: PH
-    on_custom: 
-      then:
-        - lambda: 
-            id(result_ph).publish_state(x);
-    on_calibration: 
-      then:
-        - lambda: 
-            id(result_ph).publish_state(x);
-    on_device_information: 
-      then:
-        - lambda: 
-            id(result_ph).publish_state(x);
-    on_slope: 
-      then:
-        - lambda: 
-            id(result_ph).publish_state(x);
-    on_t: 
-      then:
-        - lambda: 
-            id(result_ph).publish_state(x); 
-
-  # EZO Circuit - EC
-  # Conductivity Probe
-  - platform: ezo
-    icon: mdi:shaker-outline
-    # name: "Salinity"
-    id: ec_ezo
-    address: ${addEC}
-    unit_of_measurement: "ppt"
-    accuracy_decimals: 2
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    on_custom: 
-      then:
-        - lambda: 
-            id(raw_value_ec).publish_state(x);
-    on_calibration: 
-      then:
-        - lambda: 
-            id(result_ec).publish_state(x);
-    on_device_information: 
-      then:
-        - lambda: 
-            id(result_ec).publish_state(x);
-    on_slope: 
-      then:
-        - lambda: 
-            id(result_ec).publish_state(x);
-    on_t: 
-      then:
-        - lambda: 
-            id(result_ec).publish_state(x);
-
-  # Conductivity
-  - platform: template
-    name: Conductivity
-    id: sensor_conductivity
-    icon: mdi:lightning-bolt-outline
-    unit_of_measurement: "uS/cm"
-    accuracy_decimals: 0
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    lambda: |-
-      std::string str = id(raw_value_ec).state;
-      std::vector<std::string> v;
-      char * token;
-      char seps[] = ",";
-      token = strtok (&str[0],seps);
-      while (token != NULL) {
-        v.push_back(token);
-        token = strtok (NULL, seps);
-      }
-      if (v.size() == 4) {
-        return std::stof(v[0]);
-      } 
-      else {
-        return NULL;
-      }
-
-  # TDS
-  - platform: template
-    name: TDS
-    id: sensor_tds
-    unit_of_measurement: "mg/L"
-    icon: mdi:water-opacity
-    accuracy_decimals: 0
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    lambda: |-
-      std::string str = id(raw_value_ec).state;
-      std::vector<std::string> v;
-      char * token;
-      char seps[] = ",";
-      token = strtok (&str[0],seps);
-      while (token != NULL) {
-        v.push_back(token);
-        token = strtok (NULL, seps);
-      }
-      if (v.size() == 4) {
-        return std::stof(v[1]);
-      } 
-      else {
-        return NULL;
-      }
-
-  # Salinity
-  - platform: template
-    name: Salinity
-    id: sensor_salinity
-    icon: mdi:shaker-outline
-    unit_of_measurement: "ppt"
-    accuracy_decimals: 2
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    lambda: |-
-      std::string str = id(raw_value_ec).state;
-      std::vector<std::string> v;
-      char * token;
-      char seps[] = ",";
-      token = strtok (&str[0],seps);
-      while (token != NULL) {
-        v.push_back(token);
-        token = strtok (NULL, seps);
-      }
-      if (v.size() == 4) {
-        return std::stof(v[2]);
-      } 
-      else {
-        return NULL;
-      }
-
-  # Specific Gravity
-  - platform: template
-    name: Specific Gravity
-    id: sensor_specific_gravity
-    icon: mdi:cup-water
-    unit_of_measurement: ""
-    accuracy_decimals: 3
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    lambda: |-
-      std::string str = id(raw_value_ec).state;
-      std::vector<std::string> v;
-      char * token;
-      char seps[] = ",";
-      token = strtok (&str[0],seps);
-      while (token != NULL) {
-        v.push_back(token);
-        token = strtok (NULL, seps);
-      }
-      if (v.size() == 4) {
-        return std::stof(v[3]);
-      } 
-      else {
-        return NULL;
-      }
-
-  # EZO Circuit - RTD
-  # Temperature
-  - platform: ezo
-    icon: mdi:thermometer-lines
-    name: "Temperature EZO"
-    id: temp_ezo
-    address: ${addRTD}
-    # unit_of_measurement: "°C"
-    accuracy_decimals: 2
-    update_interval: "${update_rtd}"
-    state_class: "measurement"
-    device_class: "temperature"
-    disabled_by_default: true
-
-  # EZO Circuit - HUM
-  # Humidity
-  - platform: ezo
-    icon: mdi:water-percent
-    name: "Humidity"
-    id: hum_ezo
-    address: ${addHUM}
-    unit_of_measurement: "%"
-    accuracy_decimals: 2
-    update_interval: "${update_hum}"
-    state_class: "measurement"
-    device_class: "humidity"
-    disabled_by_default: true
-
-  # EZO Circuit - CO2
-  # Cardbon Dioxide
-  - platform: ezo
-    icon: mdi:molecule-co2
-    name: "Cardbon Dioxide"
-    id: co2_ezo
-    address: ${addCO2}
-    unit_of_measurement: "ppm"
-    accuracy_decimals: 2
-    update_interval: "${update_co2}"
-    state_class: "measurement"
-    device_class: "carbon_dioxide"
-    disabled_by_default: true
-
-  # EZO Circuit - DO
-  # Dissolved Oxygen
-  - platform: ezo
-    icon: mdi:molecule
-    name: "Dissolved Oxygen"
-    id: do_ezo
-    address: ${addDO}
-    unit_of_measurement: "mg/L"
-    accuracy_decimals: 2
-    update_interval: "${update_do}"
-    state_class: "measurement"
-    disabled_by_default: true
-
-  # EZO Circuit - pmp
-  # Pump
-  - platform: ezo
-    icon: mdi:pump
-    name: "Pump"
-    id: pmp_ezo
-    address: ${addPMP}
-    unit_of_measurement: ""
-    accuracy_decimals: 2
-    update_interval: "${update_pmp}"
-    state_class: "measurement"
-    disabled_by_default: true
-
-  # Temperature Probe 1
-  - platform: dallas
-    id: temp_1
-    icon: mdi:thermometer-lines
-    index: 0
-    name: "Temperature"
-    filters:
-      - calibrate_linear:
-          method: least_squares
-          datapoints:
-            - 0.0 -> ${cal_0}
-            - 100.0 -> ${cal_100}
-    on_value: 
-      then:
-        - component.update: temp_range
-
-  # Temperature Probe 2
-  - platform: dallas
-    id: temp_2
-    icon: mdi:thermometer-lines
-    index: 1
-    name: "Temperature 2"
-    filters:
-      - calibrate_linear:
-          method: least_squares
-          datapoints:
-            - 0.0 -> ${cal_0_2}
-            - 100.0 -> ${cal_100_2}
-    disabled_by_default: true
-    on_value: 
-      then:
-        - component.update: temp_range_2
-    
-  # Convert to Fahrenheit - Temp. 1
-  - platform: template
-    id: temp_f
-    lambda: |-
-      return id(temp_1).state * 9 / 5 + 32;
-
-  # Convert to Fahrenheit - Temp. 2
-  - platform: template
-    id: temp_f_2
-    lambda: |-
-      return id(temp_2).state * 9 / 5 + 32;
-
-  # Calibration Temp. at 0C
-  - platform: template
-    name: Calibration at 0°C - Temp. 1
-    id: cal_0_sen
-    icon: mdi:snowflake-alert
-    unit_of_measurement: "°C"
-    disabled_by_default: true
-    entity_category: "diagnostic"
-    lambda: |-
-      return {${cal_0}};
-
-  # Calibration Temp. at 100C
-  - platform: template
-    name: Calibration at 100°C - Temp. 1
-    id: cal_100_sen
-    icon: mdi:water-thermometer
-    unit_of_measurement: "°C"
-    disabled_by_default: true
-    entity_category: "diagnostic"
-    lambda: |-
-      return {${cal_100}};
-
-  # Calibration Temp. 2 at 0C
-  - platform: template
-    name: Calibration at 0°C  - Temp. 2
-    id: cal_0_2_sen
-    icon: mdi:snowflake-alert
-    unit_of_measurement: "°C"
-    disabled_by_default: true
-    entity_category: "diagnostic"
-    lambda: |-
-      return {${cal_0_2}};
-
-  # Calibration Temp. 2 at 100C
-  - platform: template
-    name: Calibration at 100°C - Temp. 2
-    id: cal_100_2_sen
-    icon: mdi:water-thermometer
-    unit_of_measurement: "°C"
-    disabled_by_default: true
-    entity_category: "diagnostic"
-    lambda: |-
-      return {${cal_100_2}};
-
-binary_sensor:
-  # Aquapi API Status
-  - platform: status
-    name: "Status"
-    
-  # Optical Sensor - LOW (yellow)
-  - platform: gpio
-    id: os_low
-    pin: 
-      number: ${opticalLowPin}
-      inverted: true
-      mode:
-        input: true
-        pullup: true
-    name: "Optical Sensor: Low"
-    filters:
-      - delayed_on_off: 30ms
-    on_state:
-      then:
-        component.update: water_level
-
-  # Optical Sensor - HIGH (blue)
-  - platform: gpio
-    id: os_high
-    pin: 
-      number: ${opticalHighPin}
-      inverted: true
-      mode:
-        input: true
-        pullup: true
-    name: "Optical Sensor: High"
-    filters:
-      - delayed_on_off: 30ms
-    on_state:
-      then:
-        component.update: water_level
-
-  # Additional Pin 1
-  - platform: gpio
-    id: aux_1
-    pin: 
-      number: ${auxPin1}
-      inverted: true
-      mode:
-        input: true
-        pullup: true
-    name: Aux 1
-    filters:
-      - delayed_on_off: 30ms
-
-  # Additional Pin 2
-  - platform: gpio
-    id: aux_2
-    pin: 
-      number: ${auxPin2}
-      inverted: true
-      mode:
-        input: true
-        pullup: true
-    name: Aux 2
-    filters:
-      - delayed_on_off: 30ms
-
-text_sensor: 
-  # Hostname
-  - platform: template
-    name: "Hostname"
-    id: hostname
-    icon: mdi:cellphone-arrow-down
-    lambda: |-
-      return {"${name}"};
-    entity_category: "diagnostic"
-
-  # Wifi Info
-  - platform: wifi_info
-    ip_address:
-      name: IP Address
-      icon: mdi:ip-network
-    ssid:
-      name: Connected SSID
-      icon: mdi:wifi-arrow-left-right
-    bssid:
-      name: Connected BSSID
-      icon: mdi:wifi-star
-    mac_address:
-      name: Mac Address
-      icon: mdi:chip
-
-  # AquaPi Version
-  - platform: template
-    name: "AquaPi Version"
-    id: aquapi_version
-    icon: mdi:update
-    update_interval: 600s
-    lambda: |-
-      return {"${app_version}"};
-    entity_category: "diagnostic"
-
-  # GitHub Project URL
-  - platform: template
-    name: GitHub
-    id: github
-    icon: mdi:github
-    lambda: |-
-      return {"github.com/TheRealFalseReality/aquapi"};
-    entity_category: "diagnostic"
-
-  # Water Level
-  - platform: template
-    icon: mdi:waves-arrow-up
-    name: "Water Level"
-    id: water_level
-    update_interval: "${update_water}"
-    lambda: |-
-      if(id(os_high).state == true && id(os_low).state == true) {
-        // Water Level is High
-        return {"High"};
-      }
-      if(id(os_high).state == false && id(os_low).state == false) {
-        // Water Level is Low
-        return {"Low"};
-      }
-      if(id(os_high).state == false && id(os_low).state == true) {
-        // Water Level is Normal
-        return {"Normal"};
-      } else {
-        return {"Uknown or Error"};
-      }
-    
-  # Temperature Range 1
-  - platform: template
-    name: Temperature Range
-    id: temp_range
-    icon: mdi:thermometer-water
-    update_interval: "${update_temp}"
-    lambda: |-
-      if(id(temp_f).state <= id(range_cool).state) {
-        return {"Cool"};
-      }
-      if(id(temp_f).state < id(range_warm).state && id(temp_f).state > id(range_cool).state) {
-        return {"OK"};
-      }
-      if(id(temp_f).state >= id(range_warm).state) {
-        return {"Warm"};
-      }     
-      else {
-        return {"Unknown"};
-      }  
-
-  # Temperature Range 2
-  - platform: template
-    name: Temperature 2 Range
-    id: temp_range_2
-    icon: mdi:thermometer-water
-    update_interval: "${update_temp}"
-    disabled_by_default: true
-    lambda: |-
-      if(id(temp_f_2).state <= id(range_cool).state) {
-        return {"Cool"};
-      }
-      if(id(temp_f_2).state < id(range_warm).state && id(temp_f_2).state > id(range_cool).state) {
-        return {"OK"};
-      }
-      if(id(temp_f_2).state >= id(range_warm).state) {
-        return {"Warm"};
-      }     
-      else {
-        return {"Unknown"};
-      }
-
-  # Conductivity Raw Value
-  - platform: template
-    name: EC - Raw Value
-    id: raw_value_ec
-    disabled_by_default: true
-    on_value: 
-      then:
-        - component.update: sensor_salinity
-        - component.update: sensor_conductivity
-        - component.update: sensor_tds
-        - component.update: sensor_specific_gravity
-
-  # Selected Command Result - pH
-  - platform: template
-    name: pH - Command Result
-    id: result_ph
-    disabled_by_default: true
-
-  # Selected Command Result - Conductivity
-  - platform: template
-    name: EC - Command Result
-    id: result_ec
-    disabled_by_default: true
-
-button:
-  # Soft Restart
-  - platform: restart
-    name: "Restart"
-
-  # Factory Reset
-  - platform: factory_reset
-    name: Factory Reset (USE WITH CAUTION)
-    disabled_by_default: true
-
-  # Safe Mode Restart
-  - platform: safe_mode
-    name: "Restart in Safe Mode"
-    id: restart_safe
-    disabled_by_default: true
-
-  # Shutdown
-  - platform: shutdown
-    name: "Shutdown"
-    disabled_by_default: true
-
-  # # EC
-  # # Output Parameters
-  # # Output Salinity
-  # - platform: template
-  #   name: "EC - Output - Salinity"
-  #   id: ec_sal
-  #   on_press:
-  #     then:
-  #       - lambda: |-
-  #           id(ec_ezo).send_custom("O,EC,0");
-  #           id(ec_ezo).send_custom("O,TDS,0");
-  #           id(ec_ezo).send_custom("O,S,1");
-  #           id(ec_ezo).send_custom("O,SG,0");
-  #   entity_category: "Config"
-  #   disabled_by_default: true
-            
-  # # Output Specific Gravity
-  # - platform: template
-  #   name: "EC - Output - Specific Gravity"
-  #   id: ec_sg
-  #   on_press:
-  #     then:
-  #       - lambda: |-
-  #           id(ec_ezo).send_custom("O,EC,0");
-  #           id(ec_ezo).send_custom("O,TDS,0");
-  #           id(ec_ezo).send_custom("O,S,0");
-  #           id(ec_ezo).send_custom("O,SG,1");
-  #   entity_category: "Config"
-  #   disabled_by_default: true
-
-  # # Output Conductivity
-  # - platform: template
-  #   name: "EC - Output - Conductivity"
-  #   id: ec_cond
-  #   on_press:
-  #     then:
-  #       - lambda: |-
-  #           id(ec_ezo).send_custom("O,EC,1");
-  #           id(ec_ezo).send_custom("O,TDS,0");
-  #           id(ec_ezo).send_custom("O,S,0");
-  #           id(ec_ezo).send_custom("O,SG,0");
-  #   entity_category: "Config"
-  #   disabled_by_default: true
-
-  # Read pH Probe
-  - platform: template
-    name: pH - Read
-    id: read_ph
-    entity_category: "Config"
-    disabled_by_default: true
-    on_press:
-      then:
-        - lambda: |-
-            id(ph_ezo).send_custom("R");
-
-  # Read Conductivity Probe
-  - platform: template
-    name: EC - Read
-    id: read_ec
-    entity_category: "Config"
-    disabled_by_default: true
-    on_press:
-      then:
-        - lambda: |-
-            id(ec_ezo).send_custom("R");
-
-  # Send Selected EZO Command - pH
-  - platform: template
-    name: pH - Command Send Selected
-    id: send_selected_ph
-    entity_category: "Config"
-    disabled_by_default: true
-    on_press:
-      then:
-        - lambda: |-
-            if (id(select_command_ph).state == "Read") {
-              id(ph_ezo).send_custom("R");
-            }
-            // Get Device Firmware Version
-            if (id(select_command_ph).state == "Information") {
-              id(ph_ezo).get_device_information();
-            }
-            if (id(select_command_ph).state == "Status") {
-              id(ph_ezo).send_custom("Status");
-            }
-            if (id(select_command_ph).state == "Get Slope") {
-              id(ph_ezo).get_slope();
-            }
-            if (id(select_command_ph).state == "Check Calibration") {
-              id(ph_ezo).get_calibration();
-            }  
-            if (id(select_command_ph).state == "Calibrate @ MID  = 7  (WILL RESET CALIBRATION)") {
-              id(ph_ezo).set_calibration_point_mid(7.00);
-            }
-            if (id(select_command_ph).state == "Calibrate @ LOW  = 4  (WILL RESET CALIBRATION)") {
-              id(ph_ezo).set_calibration_point_low(4.00);
-            }
-            if (id(select_command_ph).state == "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)") {
-              id(ph_ezo).set_calibration_point_high(10.00);
-            }
-            if (id(select_command_ph).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
-              id(ph_ezo).clear_calibration();
-            }
-
-  # Send Selected EZO Command - Conductitivy
-  - platform: template
-    name: EC - Command Send Selected
-    id: send_selected_ec
-    entity_category: "Config"
-    disabled_by_default: true
-    on_press:
-      then:
-        - lambda: |-
-            if (id(select_command_ec).state == "Read") {
-              id(ec_ezo).send_custom("R");
-            }
-            if (id(select_command_ec).state == "Information") {
-              id(ec_ezo).get_device_information();
-            }
-            if (id(select_command_ec).state == "Status") {
-              id(ec_ezo).send_custom("Status");
-            }
-            if (id(select_command_ec).state == "Get Probe K Value") {
-              id(ec_ezo).send_custom("K,?");
-            }  
-            if (id(select_command_ec).state == "Get TDS Value") {
-              id(ec_ezo).send_custom("TDS,?");
-            }  
-            if (id(select_command_ec).state == "Get Enabled Parameter(s)") {
-              id(ec_ezo).send_custom("O,?");
-            }  
-            if (id(select_command_ec).state == "Set Probe Type K1") {
-              id(ec_ezo).send_custom("K,1");
-            }
-            if (id(select_command_ec).state == "Output Units - All (Default)") {
-              id(ec_ezo).send_custom("O,EC,1");
-              id(ec_ezo).send_custom("O,TDS,1");
-              id(ec_ezo).send_custom("O,S,1");
-              id(ec_ezo).send_custom("O,SG,1");
-            }
-            if (id(select_command_ec).state == "Output Units - Conductivity") {
-              id(ec_ezo).send_custom("O,EC,1");
-              id(ec_ezo).send_custom("O,TDS,0");
-              id(ec_ezo).send_custom("O,S,0");
-              id(ec_ezo).send_custom("O,SG,0");
-            }
-            if (id(select_command_ec).state == "Salinity") {
-              id(ec_ezo).send_custom("O,EC,0");
-              id(ec_ezo).send_custom("O,TDS,0");
-              id(ec_ezo).send_custom("O,S,1");
-              id(ec_ezo).send_custom("O,SG,0");
-            }
-            if (id(select_command_ec).state == "Output Units - Specific Gravity") {
-              id(ec_ezo).send_custom("O,EC,0");
-              id(ec_ezo).send_custom("O,TDS,0");
-              id(ec_ezo).send_custom("O,S,0");
-              id(ec_ezo).send_custom("O,SG,1");
-            }
-            if (id(select_command_ec).state == "Output Units - TDS") {
-              id(ec_ezo).send_custom("O,EC,0");
-              id(ec_ezo).send_custom("O,TDS,1");
-              id(ec_ezo).send_custom("O,S,0");
-              id(ec_ezo).send_custom("O,SG,0");
-            }
-            if (id(select_command_ec).state == "Check Calibration") {
-              id(ec_ezo).get_calibration();
-            }  
-            if (id(select_command_ec).state == "Calibrate @ 0 (WILL RESET CALIBRATION)") {
-              id(ec_ezo).set_calibration_point_mid(7.00);
-            }
-            if (id(select_command_ec).state == "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)") {
-              id(ec_ezo).set_calibration_point_low(4.00);
-            }
-            if (id(select_command_ec).state == "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)") {
-              id(ec_ezo).set_calibration_point_high(10.00);
-            }
-            if (id(select_command_ec).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
-              id(ec_ezo).clear_calibration();
-            }
-
-number:
-  # Temperature when Cool
-  - platform: template
-    name: "Temp. Cool"
-    id: range_cool
-    icon: mdi:water-thermometer
-    optimistic: true
-    mode: box
-    min_value: 0.0
-    max_value: 100.0
-    step: 0.5
-    restore_value: True
-    initial_value: 72
-    entity_category: "Config"
-    on_value: 
-      then:
-        - component.update: temp_range
-        - component.update: temp_range_2
-
-  # Temperature when Warm
-  - platform: template
-    name: "Temp. Warm"
-    icon: mdi:water-alert
-    id: range_warm
-    optimistic: true
-    mode: box
-    min_value: 0.0
-    max_value: 100.0
-    step: 0.5
-    restore_value: True
-    initial_value: 82
-    entity_category: "Config"
-    on_value: 
-      then:
-        - component.update: temp_range
-        - component.update: temp_range_2
-
-select:
-  - platform: template
-    name: pH - Command Select
-    id: select_command_ph
-    optimistic: true
-    disabled_by_default: true
-    entity_category: "Config"
-    options:
-      - "Read"
-      - "Information"
-      - "Status"
-      - "Get Slope"
-      - "Check Calibration"
-      - "Calibrate @ MID = 7 (WILL RESET CALIBRATION)"
-      - "Calibrate @ LOW = 4 (WILL RESET CALIBRATION)"
-      - "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)"
-      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
-    initial_option: "Check Calibration"
-    restore_value: true
-    set_action:
-      - logger.log:
-          format: "Chosen option: %s"
-          args: ["x.c_str()"]
-
-  - platform: template
-    name: EC - Command Select
-    id: select_command_ec
-    disabled_by_default: true
-    optimistic: true
-    entity_category: "Config"
-    options:
-      - "Read"
-      - "Information"
-      - "Status"
-      - "Get Probe K Value"
-      - "Get TDS Value"
-      - "Get Enabled Parameter(s)"
-      - "Set Probe Type K1"
-      - "Output Units - All (Default)"
-      - "Output Units - Conductivity"
-      - "Output Units - Salinity"
-      - "Output Units - Specific Gravity"
-      - "Output Units - TDS"
-      - "Check Calibration"
-      - "Calibrate @ 0 (WILL RESET CALIBRATION)"
-      - "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)"
-      - "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)"
-      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
-    initial_option: "Check Calibration"
-    restore_value: true
-    set_action:
-      - logger.log:
-          format: "Chosen option: %s"
-          args: ["x.c_str()"]
\ No newline at end of file
+packages:
+  device_base: !include common/device_base.yaml
+  dallas: !include common/temperature_dallas.yaml
+  pins: !include common/binary.yaml
+  aquapi: !include common/aquapi.yaml
+  ezo_ph: !include common/ezo_ph.yaml
+  ezo_ec: !include common/ezo_ec.yaml
+  # ezo_hum: !include common/ezo_hum.yaml
+  # ezo_rtd: !include common/ezo_rtd.yaml
+  # ezo_co2: !include common/ezo_co2.yaml
+  # ezo_do: !include common/ezo_do.yaml
+  # ezo_pmp: !include common/ezo_pmp.yaml
diff --git a/common/aquapi.yaml b/common/aquapi.yaml
new file mode 100644
index 0000000..a12155a
--- /dev/null
+++ b/common/aquapi.yaml
@@ -0,0 +1,19 @@
+text_sensor: 
+  # AquaPi Version
+  - platform: template
+    name: "AquaPi Version"
+    id: aquapi_version
+    icon: mdi:update
+    update_interval: 600s
+    lambda: |-
+      return {"${app_version}"};
+    entity_category: "diagnostic"
+
+  # GitHub Project URL
+  - platform: template
+    name: GitHub
+    id: github
+    icon: mdi:github
+    lambda: |-
+      return {"github.com/TheRealFalseReality/aquapi"};
+    entity_category: "diagnostic"
\ No newline at end of file
diff --git a/common/binary.yaml b/common/binary.yaml
new file mode 100644
index 0000000..34993b4
--- /dev/null
+++ b/common/binary.yaml
@@ -0,0 +1,87 @@
+esphome:
+  on_boot: 
+      priority: 200
+      then:
+        - component.update: water_level
+
+binary_sensor:
+  # Optical Sensor - LOW (yellow)
+  - platform: gpio
+    id: os_low
+    pin: 
+      number: ${opticalLowPin}
+      inverted: true
+      mode:
+        input: true
+        pullup: true
+    name: "Optical Sensor: Low"
+    filters:
+      - delayed_on_off: 30ms
+    on_state:
+      then:
+        component.update: water_level
+
+  # Optical Sensor - HIGH (blue)
+  - platform: gpio
+    id: os_high
+    pin: 
+      number: ${opticalHighPin}
+      inverted: true
+      mode:
+        input: true
+        pullup: true
+    name: "Optical Sensor: High"
+    filters:
+      - delayed_on_off: 30ms
+    on_state:
+      then:
+        component.update: water_level
+
+  # Additional Pin 1
+  - platform: gpio
+    id: aux_1
+    pin: 
+      number: ${auxPin1}
+      inverted: true
+      mode:
+        input: true
+        pullup: true
+    name: Aux 1
+    filters:
+      - delayed_on_off: 30ms
+
+  # Additional Pin 2
+  - platform: gpio
+    id: aux_2
+    pin: 
+      number: ${auxPin2}
+      inverted: true
+      mode:
+        input: true
+        pullup: true
+    name: Aux 2
+    filters:
+      - delayed_on_off: 30ms
+
+text_sensor:
+  # Water Level
+  - platform: template
+    icon: mdi:waves-arrow-up
+    name: "Water Level"
+    id: water_level
+    update_interval: "${update_water}"
+    lambda: |-
+      if(id(os_high).state == true && id(os_low).state == true) {
+        // Water Level is High
+        return {"High"};
+      }
+      if(id(os_high).state == false && id(os_low).state == false) {
+        // Water Level is Low
+        return {"Low"};
+      }
+      if(id(os_high).state == false && id(os_low).state == true) {
+        // Water Level is Normal
+        return {"Normal"};
+      } else {
+        return {"Uknown or Error"};
+      }
\ No newline at end of file
diff --git a/common/device_base.yaml b/common/device_base.yaml
new file mode 100644
index 0000000..34eefa4
--- /dev/null
+++ b/common/device_base.yaml
@@ -0,0 +1,144 @@
+esphome:
+  name: "${name}"
+  friendly_name: "${friendly_name}"
+  # Automatically add the mac address to the name
+  # name_add_mac_suffix: true
+  comment: "${comment}"
+
+esp32:
+  board: esp32dev
+  framework:
+    type: arduino
+
+# Enable logging
+logger:
+  level: "${logger}"
+
+api:
+
+ota:
+
+wifi: 
+  ap:
+
+captive_portal:
+
+# Sets up Bluetooth LE (Only on ESP32) to allow the user to provision wifi credentials to the device.
+esp32_improv:
+  authorizer: none
+  
+improv_serial:
+
+# i2c Pins
+i2c:
+  sda: ${sdaPin}
+  scl: ${sclPin}
+  scan: true
+  id: bus_a
+
+# Internal Blue LED
+light:
+  - platform: status_led
+    id: internal_led
+    pin: GPIO2
+
+sensor:
+  # Internal Magnetic Sensor
+  - platform: esp32_hall
+    name: "ESP32 Hall Sensor"
+    entity_category: "diagnostic"
+
+  # Internal Temp.
+  - platform: internal_temperature
+    name: "Internal Temperature"
+
+  # Wifi Signal 
+  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
+    # name: "WiFi Signal dB"
+    id: wifi_signal_db
+    update_interval: 60s
+    entity_category: "diagnostic"
+
+  # Wifi %
+  - platform: copy # Reports the WiFi signal strength in %
+    source_id: wifi_signal_db
+    name: "WiFi Signal Strength"
+    filters:
+      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
+    unit_of_measurement: "%"
+    entity_category: "diagnostic"
+
+    # Uptime sensor
+  - platform: uptime
+    name: Uptime 
+
+  # of I2C devices connected
+  - platform: template
+    name: "I2C Devices Connected"
+    id: i2c_devices
+    icon: mdi:integrated-circuit-chip
+    entity_category: "diagnostic"
+    disabled_by_default: true
+    lambda: |-
+      byte error, address;
+      int nDevices;
+      nDevices = 0;
+      for(address = 1; address < 127; address++) {
+        Wire.beginTransmission(address);
+        error = Wire.endTransmission();
+        if (error == 0) {
+          nDevices++;
+        }
+      }
+      return nDevices;
+
+binary_sensor:
+  # API Status
+  - platform: status
+    name: "Status"
+
+text_sensor: 
+  # Hostname
+  - platform: template
+    name: "Hostname"
+    id: hostname
+    icon: mdi:cellphone-arrow-down
+    lambda: |-
+      return {"${name}"};
+    entity_category: "diagnostic"
+
+  # Wifi Info
+  - platform: wifi_info
+    ip_address:
+      name: IP Address
+      icon: mdi:ip-network
+    ssid:
+      name: Connected SSID
+      icon: mdi:wifi-arrow-left-right
+    bssid:
+      name: Connected BSSID
+      icon: mdi:wifi-star
+    mac_address:
+      name: Mac Address
+      icon: mdi:chip
+
+button:
+  # Soft Restart
+  - platform: restart
+    name: "Restart"
+
+  # Factory Reset
+  - platform: factory_reset
+    name: Factory Reset (USE WITH CAUTION)
+    disabled_by_default: true
+
+  # Safe Mode Restart
+  - platform: safe_mode
+    name: "Restart in Safe Mode"
+    id: restart_safe
+    disabled_by_default: true
+
+  # Shutdown
+  - platform: shutdown
+    name: "Shutdown"
+    disabled_by_default: true
\ No newline at end of file
diff --git a/common/ezo_co2.yaml b/common/ezo_co2.yaml
new file mode 100644
index 0000000..d31d3d0
--- /dev/null
+++ b/common/ezo_co2.yaml
@@ -0,0 +1,41 @@
+# esphome:
+#     on_boot: 
+#         priority: 200
+#         then:
+#           - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - CO2
+  # Cardbon Dioxide
+  - platform: ezo
+    icon: mdi:molecule-co2
+    name: "Cardbon Dioxide"
+    id: co2_ezo
+    address: ${addCO2}
+    unit_of_measurement: "ppm"
+    accuracy_decimals: 2
+    update_interval: "${update_co2}"
+    state_class: "measurement"
+    device_class: "carbon_dioxide"
+    disabled_by_default: true
+    # on_custom: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_calibration: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_device_information: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_slope: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_t: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x); 
\ No newline at end of file
diff --git a/common/ezo_do.yaml b/common/ezo_do.yaml
new file mode 100644
index 0000000..01f3bcd
--- /dev/null
+++ b/common/ezo_do.yaml
@@ -0,0 +1,40 @@
+# esphome:
+#     on_boot: 
+#         priority: 200
+#         then:
+#           - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - DO
+  # Dissolved Oxygen
+  - platform: ezo
+    icon: mdi:molecule
+    name: "Dissolved Oxygen"
+    id: do_ezo
+    address: ${addDO}
+    unit_of_measurement: "mg/L"
+    accuracy_decimals: 2
+    update_interval: "${update_do}"
+    state_class: "measurement"
+    disabled_by_default: true
+    # on_custom: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_calibration: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_device_information: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_slope: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_t: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x); 
\ No newline at end of file
diff --git a/common/ezo_ec.yaml b/common/ezo_ec.yaml
new file mode 100644
index 0000000..ecf9b7f
--- /dev/null
+++ b/common/ezo_ec.yaml
@@ -0,0 +1,289 @@
+esphome:
+    on_boot: 
+        priority: 200
+        then:
+            - button.press: read_ec
+            - button.press: send_selected_ec
+
+interval:
+  # Update Raw EC
+  - interval: "${update_ec}"
+    then:
+      - button.press: read_ec
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - EC
+  # Conductivity Probe
+  - platform: ezo
+    icon: mdi:shaker-outline
+    # name: "Salinity"
+    id: ec_ezo
+    address: ${addEC}
+    unit_of_measurement: "ppt"
+    accuracy_decimals: 2
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    on_custom: 
+      then:
+        - lambda: 
+            id(raw_value_ec).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_ec).publish_state(x);
+
+  # Conductivity
+  - platform: template
+    name: Conductivity
+    id: sensor_conductivity
+    icon: mdi:lightning-bolt-outline
+    unit_of_measurement: "uS/cm"
+    accuracy_decimals: 0
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[0]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # TDS
+  - platform: template
+    name: TDS
+    id: sensor_tds
+    unit_of_measurement: "mg/L"
+    icon: mdi:water-opacity
+    accuracy_decimals: 0
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[1]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # Salinity
+  - platform: template
+    name: Salinity
+    id: sensor_salinity
+    icon: mdi:shaker-outline
+    unit_of_measurement: "ppt"
+    accuracy_decimals: 2
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[2]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # Specific Gravity
+  - platform: template
+    name: Specific Gravity
+    id: sensor_specific_gravity
+    icon: mdi:cup-water
+    unit_of_measurement: ""
+    accuracy_decimals: 3
+    update_interval: "${update_ec}"
+    state_class: "measurement"
+    lambda: |-
+      std::string str = id(raw_value_ec).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 4) {
+        return std::stof(v[3]);
+      } 
+      else {
+        return NULL;
+      }
+
+text_sensor:
+  # Conductivity Raw Value
+  - platform: template
+    name: EC - Raw Value
+    id: raw_value_ec
+    disabled_by_default: true
+    on_value: 
+      then:
+        - component.update: sensor_salinity
+        - component.update: sensor_conductivity
+        - component.update: sensor_tds
+        - component.update: sensor_specific_gravity
+
+  # Selected Command Result - Conductivity
+  - platform: template
+    name: EC - Command Result
+    id: result_ec
+    disabled_by_default: true
+
+button:
+  # Read Conductivity Probe
+  - platform: template
+    name: EC - Read
+    id: read_ec
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(ec_ezo).send_custom("R");
+
+  # Send Selected EZO Command - Conductitivy
+  - platform: template
+    name: EC - Command Send Selected
+    id: send_selected_ec
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_ec).state == "Read") {
+              id(ec_ezo).send_custom("R");
+            }
+            if (id(select_command_ec).state == "Information") {
+              id(ec_ezo).get_device_information();
+            }
+            if (id(select_command_ec).state == "Status") {
+              id(ec_ezo).send_custom("Status");
+            }
+            if (id(select_command_ec).state == "Get Probe K Value") {
+              id(ec_ezo).send_custom("K,?");
+            }  
+            if (id(select_command_ec).state == "Get TDS Value") {
+              id(ec_ezo).send_custom("TDS,?");
+            }  
+            if (id(select_command_ec).state == "Get Enabled Parameter(s)") {
+              id(ec_ezo).send_custom("O,?");
+            }  
+            if (id(select_command_ec).state == "Set Probe Type K1") {
+              id(ec_ezo).send_custom("K,1");
+            }
+            if (id(select_command_ec).state == "Output Units - All (Default)") {
+              id(ec_ezo).send_custom("O,EC,1");
+              id(ec_ezo).send_custom("O,TDS,1");
+              id(ec_ezo).send_custom("O,S,1");
+              id(ec_ezo).send_custom("O,SG,1");
+            }
+            if (id(select_command_ec).state == "Output Units - Conductivity") {
+              id(ec_ezo).send_custom("O,EC,1");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Salinity") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,1");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Output Units - Specific Gravity") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,0");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,1");
+            }
+            if (id(select_command_ec).state == "Output Units - TDS") {
+              id(ec_ezo).send_custom("O,EC,0");
+              id(ec_ezo).send_custom("O,TDS,1");
+              id(ec_ezo).send_custom("O,S,0");
+              id(ec_ezo).send_custom("O,SG,0");
+            }
+            if (id(select_command_ec).state == "Check Calibration") {
+              id(ec_ezo).get_calibration();
+            }  
+            if (id(select_command_ec).state == "Calibrate @ 0 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_mid(7.00);
+            }
+            if (id(select_command_ec).state == "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_low(4.00);
+            }
+            if (id(select_command_ec).state == "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)") {
+              id(ec_ezo).set_calibration_point_high(10.00);
+            }
+            if (id(select_command_ec).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
+              id(ec_ezo).clear_calibration();
+            }
+
+select:
+  - platform: template
+    name: EC - Command Select
+    id: select_command_ec
+    disabled_by_default: true
+    optimistic: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Probe K Value"
+      - "Get TDS Value"
+      - "Get Enabled Parameter(s)"
+      - "Set Probe Type K1"
+      - "Output Units - All (Default)"
+      - "Output Units - Conductivity"
+      - "Output Units - Salinity"
+      - "Output Units - Specific Gravity"
+      - "Output Units - TDS"
+      - "Check Calibration"
+      - "Calibrate @ 0 (WILL RESET CALIBRATION)"
+      - "Calibrate @ LOW = 12880 (WILL RESET CALIBRATION)"
+      - "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)"
+      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
+    initial_option: "Check Calibration"
+    restore_value: true
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
\ No newline at end of file
diff --git a/common/ezo_hum.yaml b/common/ezo_hum.yaml
new file mode 100644
index 0000000..9e91862
--- /dev/null
+++ b/common/ezo_hum.yaml
@@ -0,0 +1,41 @@
+# esphome:
+#     on_boot: 
+#         priority: 200
+#         then:
+#           - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - HUM
+  # Humidity
+  - platform: ezo
+    icon: mdi:water-percent
+    name: "Humidity"
+    id: hum_ezo
+    address: ${addHUM}
+    unit_of_measurement: "%"
+    accuracy_decimals: 2
+    update_interval: "${update_hum}"
+    state_class: "measurement"
+    device_class: "humidity"
+    disabled_by_default: true
+    # on_custom: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_calibration: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_device_information: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_slope: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_t: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x); 
\ No newline at end of file
diff --git a/common/ezo_ph.yaml b/common/ezo_ph.yaml
new file mode 100644
index 0000000..9eca105
--- /dev/null
+++ b/common/ezo_ph.yaml
@@ -0,0 +1,120 @@
+esphome:
+    on_boot: 
+        priority: 200
+        then:
+          - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - pH
+  - platform: ezo
+    icon: mdi:ph
+    name: "pH"
+    id: ph_ezo
+    address: ${addPH}
+    unit_of_measurement: ""
+    accuracy_decimals: 2
+    update_interval: "${update_ph}"
+    state_class: "measurement"
+    device_class: PH
+    on_custom: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_ph).publish_state(x); 
+
+text_sensor:
+  # Selected Command Result - pH
+  - platform: template
+    name: pH - Command Result
+    id: result_ph
+    disabled_by_default: true
+
+button:
+  # Read pH Probe
+  - platform: template
+    name: pH - Read
+    id: read_ph
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(ph_ezo).send_custom("R");
+
+  # Send Selected EZO Command - pH
+  - platform: template
+    name: pH - Command Send Selected
+    id: send_selected_ph
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_ph).state == "Read") {
+              id(ph_ezo).send_custom("R");
+            }
+            // Get Device Firmware Version
+            if (id(select_command_ph).state == "Information") {
+              id(ph_ezo).get_device_information();
+            }
+            if (id(select_command_ph).state == "Status") {
+              id(ph_ezo).send_custom("Status");
+            }
+            if (id(select_command_ph).state == "Get Slope") {
+              id(ph_ezo).get_slope();
+            }
+            if (id(select_command_ph).state == "Check Calibration") {
+              id(ph_ezo).get_calibration();
+            }  
+            if (id(select_command_ph).state == "Calibrate @ MID  = 7  (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_mid(7.00);
+            }
+            if (id(select_command_ph).state == "Calibrate @ LOW  = 4  (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_low(4.00);
+            }
+            if (id(select_command_ph).state == "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)") {
+              id(ph_ezo).set_calibration_point_high(10.00);
+            }
+            if (id(select_command_ph).state == "Calibrate CLEAR (WILL RESET CALIBRATION)") {
+              id(ph_ezo).clear_calibration();
+            }
+
+select:
+  - platform: template
+    name: pH - Command Select
+    id: select_command_ph
+    optimistic: true
+    disabled_by_default: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Slope"
+      - "Check Calibration"
+      - "Calibrate @ MID = 7 (WILL RESET CALIBRATION)"
+      - "Calibrate @ LOW = 4 (WILL RESET CALIBRATION)"
+      - "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)"
+      - "Calibrate CLEAR (WILL RESET CALIBRATION)"
+    initial_option: "Check Calibration"
+    restore_value: true
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
\ No newline at end of file
diff --git a/common/ezo_pmp.yaml b/common/ezo_pmp.yaml
new file mode 100644
index 0000000..5c9509a
--- /dev/null
+++ b/common/ezo_pmp.yaml
@@ -0,0 +1,40 @@
+# esphome:
+#     on_boot: 
+#         priority: 200
+#         then:
+#           - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - pmp
+  # Pump
+  - platform: ezo
+    icon: mdi:pump
+    name: "Pump"
+    id: pmp_ezo
+    address: ${addPMP}
+    unit_of_measurement: ""
+    accuracy_decimals: 2
+    update_interval: "${update_pmp}"
+    state_class: "measurement"
+    disabled_by_default: true
+    # on_custom: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_calibration: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_device_information: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_slope: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_t: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x); 
\ No newline at end of file
diff --git a/common/ezo_rtd.yaml b/common/ezo_rtd.yaml
new file mode 100644
index 0000000..20ce190
--- /dev/null
+++ b/common/ezo_rtd.yaml
@@ -0,0 +1,41 @@
+# esphome:
+#     on_boot: 
+#         priority: 200
+#         then:
+#           - button.press: send_selected_ph
+
+sensor:
+  # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
+  # EZO Circuit - RTD
+  # Temperature
+  - platform: ezo
+    icon: mdi:thermometer-lines
+    name: "Temperature EZO"
+    id: temp_ezo
+    address: ${addRTD}
+    # unit_of_measurement: "°C"
+    accuracy_decimals: 2
+    update_interval: "${update_rtd}"
+    state_class: "measurement"
+    device_class: "temperature"
+    disabled_by_default: true
+    # on_custom: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_calibration: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_device_information: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_slope: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x);
+    # on_t: 
+    #   then:
+    #     - lambda: 
+    #         id(result_ph).publish_state(x); 
\ No newline at end of file
diff --git a/common/temperature_dallas.yaml b/common/temperature_dallas.yaml
new file mode 100644
index 0000000..a5310b2
--- /dev/null
+++ b/common/temperature_dallas.yaml
@@ -0,0 +1,173 @@
+# 18B20 sensor Pin
+dallas:
+  - pin: ${dallasPin}
+    update_interval: "${update_temp}"
+
+sensor:
+  # Temperature Probe 1
+  - platform: dallas
+    id: temp_1
+    icon: mdi:thermometer-lines
+    index: 0
+    name: "Temperature"
+    filters:
+      - calibrate_linear:
+          method: least_squares
+          datapoints:
+            - 0.0 -> ${cal_0}
+            - 100.0 -> ${cal_100}
+    on_value: 
+      then:
+        - component.update: temp_range
+
+  # Temperature Probe 2
+  - platform: dallas
+    id: temp_2
+    icon: mdi:thermometer-lines
+    index: 1
+    name: "Temperature 2"
+    filters:
+      - calibrate_linear:
+          method: least_squares
+          datapoints:
+            - 0.0 -> ${cal_0_2}
+            - 100.0 -> ${cal_100_2}
+    disabled_by_default: true
+    on_value: 
+      then:
+        - component.update: temp_range_2
+
+  # Convert to Fahrenheit - Temp. 1
+  - platform: template
+    id: temp_f
+    lambda: |-
+      return id(temp_1).state * 9 / 5 + 32;
+
+  # Convert to Fahrenheit - Temp. 2
+  - platform: template
+    id: temp_f_2
+    lambda: |-
+      return id(temp_2).state * 9 / 5 + 32;
+
+  # Calibration Temp. at 0C
+  - platform: template
+    name: Calibration at 0°C - Temp. 1
+    id: cal_0_sen
+    icon: mdi:snowflake-alert
+    unit_of_measurement: "°C"
+    disabled_by_default: true
+    entity_category: "diagnostic"
+    lambda: |-
+      return {${cal_0}};
+
+  # Calibration Temp. at 100C
+  - platform: template
+    name: Calibration at 100°C - Temp. 1
+    id: cal_100_sen
+    icon: mdi:water-thermometer
+    unit_of_measurement: "°C"
+    disabled_by_default: true
+    entity_category: "diagnostic"
+    lambda: |-
+      return {${cal_100}};
+
+  # Calibration Temp. 2 at 0C
+  - platform: template
+    name: Calibration at 0°C  - Temp. 2
+    id: cal_0_2_sen
+    icon: mdi:snowflake-alert
+    unit_of_measurement: "°C"
+    disabled_by_default: true
+    entity_category: "diagnostic"
+    lambda: |-
+      return {${cal_0_2}};
+
+  # Calibration Temp. 2 at 100C
+  - platform: template
+    name: Calibration at 100°C - Temp. 2
+    id: cal_100_2_sen
+    icon: mdi:water-thermometer
+    unit_of_measurement: "°C"
+    disabled_by_default: true
+    entity_category: "diagnostic"
+    lambda: |-
+      return {${cal_100_2}};
+
+text_sensor:
+  # Temperature Range 1
+  - platform: template
+    name: Temperature Range
+    id: temp_range
+    icon: mdi:thermometer-water
+    update_interval: "${update_temp}"
+    lambda: |-
+      if(id(temp_f).state <= id(range_cool).state) {
+        return {"Cool"};
+      }
+      if(id(temp_f).state < id(range_warm).state && id(temp_f).state > id(range_cool).state) {
+        return {"OK"};
+      }
+      if(id(temp_f).state >= id(range_warm).state) {
+        return {"Warm"};
+      }     
+      else {
+        return {"Unknown"};
+      }  
+
+  # Temperature Range 2
+  - platform: template
+    name: Temperature 2 Range
+    id: temp_range_2
+    icon: mdi:thermometer-water
+    update_interval: "${update_temp}"
+    disabled_by_default: true
+    lambda: |-
+      if(id(temp_f_2).state <= id(range_cool).state) {
+        return {"Cool"};
+      }
+      if(id(temp_f_2).state < id(range_warm).state && id(temp_f_2).state > id(range_cool).state) {
+        return {"OK"};
+      }
+      if(id(temp_f_2).state >= id(range_warm).state) {
+        return {"Warm"};
+      }     
+      else {
+        return {"Unknown"};
+      }
+
+number:
+  # Temperature when Cool
+  - platform: template
+    name: "Temp. Cool"
+    id: range_cool
+    icon: mdi:water-thermometer
+    optimistic: true
+    mode: box
+    min_value: 0.0
+    max_value: 100.0
+    step: 0.5
+    restore_value: True
+    initial_value: 72
+    entity_category: "Config"
+    on_value: 
+      then:
+        - component.update: temp_range
+        - component.update: temp_range_2
+
+  # Temperature when Warm
+  - platform: template
+    name: "Temp. Warm"
+    icon: mdi:water-alert
+    id: range_warm
+    optimistic: true
+    mode: box
+    min_value: 0.0
+    max_value: 100.0
+    step: 0.5
+    restore_value: True
+    initial_value: 82
+    entity_category: "Config"
+    on_value: 
+      then:
+        - component.update: temp_range
+        - component.update: temp_range_2
\ No newline at end of file

From ebe386eb259318c0fb983351022a2f9e390ecaf5 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 01:08:54 -0500
Subject: [PATCH 12/26] Update device_base.yaml

---
 common/device_base.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/device_base.yaml b/common/device_base.yaml
index 34eefa4..9cebd91 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -2,7 +2,7 @@ esphome:
   name: "${name}"
   friendly_name: "${friendly_name}"
   # Automatically add the mac address to the name
-  # name_add_mac_suffix: true
+  name_add_mac_suffix: true
   comment: "${comment}"
 
 esp32:

From 04b458349f1f2d1da84f4a7b4686657eacd74009 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 01:13:49 -0500
Subject: [PATCH 13/26] update to dashboard project

---
 aquapi_config.yaml      |  1 -
 common/device_base.yaml | 11 +++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index e1b2193..2a4d067 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -6,7 +6,6 @@ substitutions:
   app_version: "1.3"
   # Comment
   comment: "AquaPi ESP32 - Aquarium Controller & Monitor"  
-  
   # Import Config
   import_config: "false"
   # Logger Level
diff --git a/common/device_base.yaml b/common/device_base.yaml
index 9cebd91..a8a4e11 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -4,12 +4,23 @@ esphome:
   # Automatically add the mac address to the name
   name_add_mac_suffix: true
   comment: "${comment}"
+  project:
+    name: TheRealFalseReality.aquapi
+    version: "${app_version}"
+  on_boot: 
+    priority: 200
+    then:
+      - component.update: water_level  
 
 esp32:
   board: esp32dev
   framework:
     type: arduino
 
+dashboard_import:
+  package_import_url: github://TheRealFalseReality/aquapi/aquapi_config.yaml@main
+  import_full_config: ${import_config}
+
 # Enable logging
 logger:
   level: "${logger}"

From 78898f825c301205d942f2a292b14f920a370cba Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 01:18:16 -0500
Subject: [PATCH 14/26] add suffix

---
 aquapi_config.yaml      | 2 ++
 common/device_base.yaml | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 2a4d067..aecd48e 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -6,6 +6,8 @@ substitutions:
   app_version: "1.3"
   # Comment
   comment: "AquaPi ESP32 - Aquarium Controller & Monitor"  
+  # Add MAC address to name
+  suffix: "true"
   # Import Config
   import_config: "false"
   # Logger Level
diff --git a/common/device_base.yaml b/common/device_base.yaml
index a8a4e11..c27498a 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -2,7 +2,7 @@ esphome:
   name: "${name}"
   friendly_name: "${friendly_name}"
   # Automatically add the mac address to the name
-  name_add_mac_suffix: true
+  name_add_mac_suffix: ${suffix}
   comment: "${comment}"
   project:
     name: TheRealFalseReality.aquapi

From 32faa90af04fcccde92a0a450d14c4bbf81178c2 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 01:21:22 -0500
Subject: [PATCH 15/26] small comment

---
 aquapi_config.yaml      | 9 +++------
 common/device_base.yaml | 2 +-
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index aecd48e..2889e8d 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -4,14 +4,11 @@ substitutions:
   friendly_name: "AquaPi"
   # App Version - Updated: 8/2023
   app_version: "1.3"
-  # Comment
-  comment: "AquaPi ESP32 - Aquarium Controller & Monitor"  
   # Add MAC address to name
   suffix: "true"
   # Import Config
   import_config: "false"
-  # Logger Level
-  # Can use VERBOSE for more information
+  # Logger Level - Can use VERBOSE for more information
   logger: "DEBUG"
 
   # pins
@@ -40,7 +37,7 @@ substitutions:
   addCO2: "105"
 
   # Calibration variables
-  # 0C using Ice Water; 100C using Boiling Water  
+  # 0C using Ice Water; 100C using Boiling Water
   # Calibration Temp. 1
   cal_0: "0.0"
   cal_100: "100.0"
@@ -79,4 +76,4 @@ packages:
   # ezo_rtd: !include common/ezo_rtd.yaml
   # ezo_co2: !include common/ezo_co2.yaml
   # ezo_do: !include common/ezo_do.yaml
-  # ezo_pmp: !include common/ezo_pmp.yaml
+  # ezo_pmp: !include common/ezo_pmp.yaml
\ No newline at end of file
diff --git a/common/device_base.yaml b/common/device_base.yaml
index c27498a..f6c4bc3 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -3,7 +3,7 @@ esphome:
   friendly_name: "${friendly_name}"
   # Automatically add the mac address to the name
   name_add_mac_suffix: ${suffix}
-  comment: "${comment}"
+  comment: "AquaPi ESP32 - Aquarium Controller & Monitor"
   project:
     name: TheRealFalseReality.aquapi
     version: "${app_version}"

From 73ab7609a54c1dd39b956ce5af9651ba054db2cb Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 13:36:20 -0500
Subject: [PATCH 16/26] added custom commands

---
 aquapi_config.yaml      |  1 +
 common/ezo_command.yaml | 25 +++++++++++++++++
 common/ezo_ec.yaml      | 59 +++++++++++++++++++++--------------------
 3 files changed, 56 insertions(+), 29 deletions(-)
 create mode 100644 common/ezo_command.yaml

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 2889e8d..1bff28b 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -70,6 +70,7 @@ packages:
   dallas: !include common/temperature_dallas.yaml
   pins: !include common/binary.yaml
   aquapi: !include common/aquapi.yaml
+  ezo_command: !include common/ezo_command.yaml
   ezo_ph: !include common/ezo_ph.yaml
   ezo_ec: !include common/ezo_ec.yaml
   # ezo_hum: !include common/ezo_hum.yaml
diff --git a/common/ezo_command.yaml b/common/ezo_command.yaml
new file mode 100644
index 0000000..8f3a298
--- /dev/null
+++ b/common/ezo_command.yaml
@@ -0,0 +1,25 @@
+text_sensor:
+  # Custom Command Result
+  - platform: template
+    name: EZO - Custom Command Result
+    id: result_generic
+    disabled_by_default: true
+
+button:
+  # Send EZO Command - Custom
+  - platform: template
+    name: EZO - Send Custom Command
+    id: send_custom
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(commmand_custom).state;
+
+text:
+    platform: template
+    name: EZO - Custom Command
+    id: commmand_custom
+    mode: text
+    optimistic: true
\ No newline at end of file
diff --git a/common/ezo_ec.yaml b/common/ezo_ec.yaml
index ecf9b7f..587f721 100644
--- a/common/ezo_ec.yaml
+++ b/common/ezo_ec.yaml
@@ -14,13 +14,13 @@ interval:
 sensor:
   # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
   # EZO Circuit - EC
-  # Conductivity Probe
+  # Conductivity
   - platform: ezo
     icon: mdi:shaker-outline
-    # name: "Salinity"
+    name: "Conductivity"
     id: ec_ezo
     address: ${addEC}
-    unit_of_measurement: "ppt"
+    unit_of_measurement: "uS/cm"
     accuracy_decimals: 2
     update_interval: "${update_ec}"
     state_class: "measurement"
@@ -45,31 +45,31 @@ sensor:
         - lambda: 
             id(result_ec).publish_state(x);
 
-  # Conductivity
-  - platform: template
-    name: Conductivity
-    id: sensor_conductivity
-    icon: mdi:lightning-bolt-outline
-    unit_of_measurement: "uS/cm"
-    accuracy_decimals: 0
-    update_interval: "${update_ec}"
-    state_class: "measurement"
-    lambda: |-
-      std::string str = id(raw_value_ec).state;
-      std::vector<std::string> v;
-      char * token;
-      char seps[] = ",";
-      token = strtok (&str[0],seps);
-      while (token != NULL) {
-        v.push_back(token);
-        token = strtok (NULL, seps);
-      }
-      if (v.size() == 4) {
-        return std::stof(v[0]);
-      } 
-      else {
-        return NULL;
-      }
+  # # Conductivity
+  # - platform: template
+  #   name: Conductivity
+  #   id: sensor_conductivity
+  #   icon: mdi:lightning-bolt-outline
+  #   unit_of_measurement: "uS/cm"
+  #   accuracy_decimals: 0
+  #   update_interval: "${update_ec}"
+  #   state_class: "measurement"
+  #   lambda: |-
+  #     std::string str = id(raw_value_ec).state;
+  #     std::vector<std::string> v;
+  #     char * token;
+  #     char seps[] = ",";
+  #     token = strtok (&str[0],seps);
+  #     while (token != NULL) {
+  #       v.push_back(token);
+  #       token = strtok (NULL, seps);
+  #     }
+  #     if (v.size() == 4) {
+  #       return std::stof(v[0]);
+  #     } 
+  #     else {
+  #       return NULL;
+  #     }
 
   # TDS
   - platform: template
@@ -78,6 +78,7 @@ sensor:
     unit_of_measurement: "mg/L"
     icon: mdi:water-opacity
     accuracy_decimals: 0
+    disabled_by_default: true
     update_interval: "${update_ec}"
     state_class: "measurement"
     lambda: |-
@@ -158,7 +159,7 @@ text_sensor:
     on_value: 
       then:
         - component.update: sensor_salinity
-        - component.update: sensor_conductivity
+        # - component.update: sensor_conductivity
         - component.update: sensor_tds
         - component.update: sensor_specific_gravity
 

From a6e55e12e1728439bac228e3e756a1da30ae1295 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 13:40:13 -0500
Subject: [PATCH 17/26] updates

---
 aquapi_config.yaml      | 2 +-
 common/ezo_command.yaml | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 1bff28b..a239f9f 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -3,7 +3,7 @@ substitutions:
   name: "aquapi"
   friendly_name: "AquaPi"
   # App Version - Updated: 8/2023
-  app_version: "1.3"
+  app_version: "1.3.1"
   # Add MAC address to name
   suffix: "true"
   # Import Config
diff --git a/common/ezo_command.yaml b/common/ezo_command.yaml
index 8f3a298..0b004dd 100644
--- a/common/ezo_command.yaml
+++ b/common/ezo_command.yaml
@@ -21,5 +21,6 @@ text:
     platform: template
     name: EZO - Custom Command
     id: commmand_custom
+    disabled_by_default: true
     mode: text
     optimistic: true
\ No newline at end of file

From 7027412738b836ad2286f3342b9c2ac118b2ddab Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 14:17:50 -0500
Subject: [PATCH 18/26] updates

---
 aquapi_config.yaml      | 2 +-
 common/ezo_command.yaml | 8 +-------
 common/ezo_ec.yaml      | 1 -
 common/ezo_ph.yaml      | 1 -
 4 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index a239f9f..37ae313 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -70,7 +70,7 @@ packages:
   dallas: !include common/temperature_dallas.yaml
   pins: !include common/binary.yaml
   aquapi: !include common/aquapi.yaml
-  ezo_command: !include common/ezo_command.yaml
+  # ezo_command: !include common/ezo_command.yaml
   ezo_ph: !include common/ezo_ph.yaml
   ezo_ec: !include common/ezo_ec.yaml
   # ezo_hum: !include common/ezo_hum.yaml
diff --git a/common/ezo_command.yaml b/common/ezo_command.yaml
index 0b004dd..d920a82 100644
--- a/common/ezo_command.yaml
+++ b/common/ezo_command.yaml
@@ -1,10 +1,3 @@
-text_sensor:
-  # Custom Command Result
-  - platform: template
-    name: EZO - Custom Command Result
-    id: result_generic
-    disabled_by_default: true
-
 button:
   # Send EZO Command - Custom
   - platform: template
@@ -22,5 +15,6 @@ text:
     name: EZO - Custom Command
     id: commmand_custom
     disabled_by_default: true
+    entity_category: "Config"
     mode: text
     optimistic: true
\ No newline at end of file
diff --git a/common/ezo_ec.yaml b/common/ezo_ec.yaml
index 587f721..203da5c 100644
--- a/common/ezo_ec.yaml
+++ b/common/ezo_ec.yaml
@@ -283,7 +283,6 @@ select:
       - "Calibrate @ HIGH = 80000 (WILL RESET CALIBRATION)"
       - "Calibrate CLEAR (WILL RESET CALIBRATION)"
     initial_option: "Check Calibration"
-    restore_value: true
     set_action:
       - logger.log:
           format: "Chosen option: %s"
diff --git a/common/ezo_ph.yaml b/common/ezo_ph.yaml
index 9eca105..42d9ee1 100644
--- a/common/ezo_ph.yaml
+++ b/common/ezo_ph.yaml
@@ -113,7 +113,6 @@ select:
       - "Calibrate @ HIGH = 10 (WILL RESET CALIBRATION)"
       - "Calibrate CLEAR (WILL RESET CALIBRATION)"
     initial_option: "Check Calibration"
-    restore_value: true
     set_action:
       - logger.log:
           format: "Chosen option: %s"

From c568ce4c5b4a7c3ec5b2f821aa93ed3568cb437a Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 14:51:30 -0500
Subject: [PATCH 19/26] icons added

---
 common/ezo_ec.yaml  | 2 ++
 common/ezo_ph.yaml  | 1 +
 common/ezo_rtd.yaml | 3 +--
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/common/ezo_ec.yaml b/common/ezo_ec.yaml
index 203da5c..c9a2488 100644
--- a/common/ezo_ec.yaml
+++ b/common/ezo_ec.yaml
@@ -155,6 +155,7 @@ text_sensor:
   - platform: template
     name: EC - Raw Value
     id: raw_value_ec
+    icon: mdi:counter
     disabled_by_default: true
     on_value: 
       then:
@@ -166,6 +167,7 @@ text_sensor:
   # Selected Command Result - Conductivity
   - platform: template
     name: EC - Command Result
+    icon: mdi:data-matrix
     id: result_ec
     disabled_by_default: true
 
diff --git a/common/ezo_ph.yaml b/common/ezo_ph.yaml
index 42d9ee1..d1ebff6 100644
--- a/common/ezo_ph.yaml
+++ b/common/ezo_ph.yaml
@@ -42,6 +42,7 @@ text_sensor:
   # Selected Command Result - pH
   - platform: template
     name: pH - Command Result
+    icon: mdi:data-matrix
     id: result_ph
     disabled_by_default: true
 
diff --git a/common/ezo_rtd.yaml b/common/ezo_rtd.yaml
index 20ce190..b4bca76 100644
--- a/common/ezo_rtd.yaml
+++ b/common/ezo_rtd.yaml
@@ -9,11 +9,10 @@ sensor:
   # EZO Circuit - RTD
   # Temperature
   - platform: ezo
-    icon: mdi:thermometer-lines
     name: "Temperature EZO"
     id: temp_ezo
     address: ${addRTD}
-    # unit_of_measurement: "°C"
+    unit_of_measurement: "°C"
     accuracy_decimals: 2
     update_interval: "${update_rtd}"
     state_class: "measurement"

From c61cfdc48ac672302ecafe2e8280caa9bd8b9148 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 15:41:11 -0500
Subject: [PATCH 20/26] added HUM

---
 aquapi_config.yaml      |  10 +-
 common/device_base.yaml |   1 +
 common/ezo_co2.yaml     | 166 ++++++++++++++++++++++++++-----
 common/ezo_hum.yaml     | 211 +++++++++++++++++++++++++++++++++++-----
 4 files changed, 330 insertions(+), 58 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 37ae313..1c2013e 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -73,8 +73,8 @@ packages:
   # ezo_command: !include common/ezo_command.yaml
   ezo_ph: !include common/ezo_ph.yaml
   ezo_ec: !include common/ezo_ec.yaml
-  # ezo_hum: !include common/ezo_hum.yaml
-  # ezo_rtd: !include common/ezo_rtd.yaml
-  # ezo_co2: !include common/ezo_co2.yaml
-  # ezo_do: !include common/ezo_do.yaml
-  # ezo_pmp: !include common/ezo_pmp.yaml
\ No newline at end of file
+  ezo_hum: !include common/ezo_hum.yaml
+  ezo_rtd: !include common/ezo_rtd.yaml
+  ezo_co2: !include common/ezo_co2.yaml
+  ezo_do: !include common/ezo_do.yaml
+  ezo_pmp: !include common/ezo_pmp.yaml
\ No newline at end of file
diff --git a/common/device_base.yaml b/common/device_base.yaml
index f6c4bc3..7e17d7f 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -129,6 +129,7 @@ text_sensor:
     bssid:
       name: Connected BSSID
       icon: mdi:wifi-star
+      disabled_by_default: true
     mac_address:
       name: Mac Address
       icon: mdi:chip
diff --git a/common/ezo_co2.yaml b/common/ezo_co2.yaml
index d31d3d0..056f25c 100644
--- a/common/ezo_co2.yaml
+++ b/common/ezo_co2.yaml
@@ -1,8 +1,15 @@
-# esphome:
-#     on_boot: 
-#         priority: 200
-#         then:
-#           - button.press: send_selected_ph
+esphome:
+    on_boot: 
+        priority: 200
+        then:
+            - button.press: read_co2
+            - button.press: send_selected_co2
+
+interval:
+  # Update Raw CO2
+  - interval: "${update_co2}"
+    then:
+      - button.press: read_co2
 
 sensor:
   # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
@@ -14,28 +21,135 @@ sensor:
     id: co2_ezo
     address: ${addCO2}
     unit_of_measurement: "ppm"
-    accuracy_decimals: 2
+    accuracy_decimals: 0
     update_interval: "${update_co2}"
     state_class: "measurement"
     device_class: "carbon_dioxide"
+    on_custom: 
+      then:
+        - lambda: 
+            id(raw_value_co2).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_co2).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_co2).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_co2).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_co2).publish_state(x);
+
+  # Internal Temperature
+  - platform: template
+    name: CO2 Internal Temperature
+    id: sensor_co2_internal_temperature
+    accuracy_decimals: 2
+    disabled_by_default: true
+    unit_of_measurement: "°C"
+    update_interval: "${update_co2}"
+    state_class: "measurement"
+    device_class: "temperature"
+    lambda: |-
+      std::string str = id(raw_value_co2).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 2) {
+        return std::stof(v[1]);
+      } 
+      else {
+        return NULL;
+      }
+
+text_sensor:
+  # CO2 Raw Value
+  - platform: template
+    name: CO2 - Raw Value
+    icon: mdi:counter
+    id: raw_value_co2
+    disabled_by_default: true
+    on_value: 
+      then:
+        - component.update: sensor_co2_internal_temperature
+
+  # Selected Command Result - CO2
+  - platform: template
+    name: CO2 - Command Result
+    id: result_co2
+    disabled_by_default: true
+
+button:
+  # Read CO2 Sensor
+  - platform: template
+    name: CO2 - Read
+    id: read_co2
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(co2_ezo).send_custom("R");
+
+  # Send Selected EZO Command - CO2
+  - platform: template
+    name: CO2 - Command Send Selected
+    id: send_selected_co2
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_co2).state == "Read") {
+              id(co2_ezo).send_custom("R");
+            }
+            if (id(select_command_co2).state == "Information") {
+              id(co2_ezo).get_device_information();
+            }
+            if (id(select_command_co2).state == "Status") {
+              id(co2_ezo).send_custom("Status");
+            }
+            if (id(select_command_co2).state == "Get Enabled Parameter(s)") {
+              id(co2_ezo).send_custom("O,?");
+            }  
+            if (id(select_command_co2).state == "Output Units - Enable Temperature") {
+              id(co2_ezo).send_custom("O,t,1");
+            }
+            if (id(select_command_co2).state == "Output Units - Disable Temperature") {
+              id(co2_ezo).send_custom("O,t,0");
+            }
+            if (id(select_command_co2).state == "Check Calibration") {
+              id(co2_ezo).get_calibration();
+            }
+
+select:
+  - platform: template
+    name: CO2 - Command Select
+    id: select_command_co2
     disabled_by_default: true
-    # on_custom: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_calibration: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_device_information: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_slope: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_t: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x); 
\ No newline at end of file
+    optimistic: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Enabled Parameter(s)"
+      - "Output Units - Enable Temperature"
+      - "Output Units - Disable Temperature"
+      - "Check Calibration"
+    initial_option: "Check Calibration"
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
\ No newline at end of file
diff --git a/common/ezo_hum.yaml b/common/ezo_hum.yaml
index 9e91862..25138c7 100644
--- a/common/ezo_hum.yaml
+++ b/common/ezo_hum.yaml
@@ -1,41 +1,198 @@
-# esphome:
-#     on_boot: 
-#         priority: 200
-#         then:
-#           - button.press: send_selected_ph
+esphome:
+    on_boot: 
+        priority: 200
+        then:
+            - button.press: read_hum
+            - button.press: send_selected_hum
+
+interval:
+  # Update Raw HUM
+  - interval: "${update_hum}"
+    then:
+      - button.press: read_hum
 
 sensor:
   # EZO Circuits (yellow - SCL/RX, blue - SDA/TX)
   # EZO Circuit - HUM
   # Humidity
   - platform: ezo
-    icon: mdi:water-percent
     name: "Humidity"
     id: hum_ezo
     address: ${addHUM}
     unit_of_measurement: "%"
-    accuracy_decimals: 2
+    accuracy_decimals: 0
     update_interval: "${update_hum}"
     state_class: "measurement"
     device_class: "humidity"
+    on_custom: 
+      then:
+        - lambda: 
+            id(raw_value_hum).publish_state(x);
+    on_calibration: 
+      then:
+        - lambda: 
+            id(result_hum).publish_state(x);
+    on_device_information: 
+      then:
+        - lambda: 
+            id(result_hum).publish_state(x);
+    on_slope: 
+      then:
+        - lambda: 
+            id(result_hum).publish_state(x);
+    on_t: 
+      then:
+        - lambda: 
+            id(result_hum).publish_state(x);
+
+  # Air Temperature
+  - platform: template
+    name: Air Temperature
+    id: sensor_hum_air_temperature
+    accuracy_decimals: 2
+    disabled_by_default: true
+    unit_of_measurement: "°C"
+    update_interval: "${update_hum}"
+    state_class: "measurement"
+    device_class: "temperature"
+    lambda: |-
+      std::string str = id(raw_value_hum).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 3) {
+        return std::stof(v[1]);
+      } 
+      else {
+        return NULL;
+      }
+
+  # Dew Point
+  - platform: template
+    name: Dew Point
+    id: sensor_hum_dew_point
+    accuracy_decimals: 2
+    disabled_by_default: true
+    unit_of_measurement: "°C"
+    update_interval: "${update_hum}"
+    state_class: "measurement"
+    device_class: "temperature"
+    lambda: |-
+      std::string str = id(raw_value_hum).state;
+      std::vector<std::string> v;
+      char * token;
+      char seps[] = ",";
+      token = strtok (&str[0],seps);
+      while (token != NULL) {
+        v.push_back(token);
+        token = strtok (NULL, seps);
+      }
+      if (v.size() == 3) {
+        return std::stof(v[2]);
+      } 
+      else {
+        return NULL;
+      }
+
+text_sensor:
+  # HUM Raw Value
+  - platform: template
+    name: HUM - Raw Value
+    icon: mdi:counter
+    id: raw_value_hum
+    disabled_by_default: true
+    on_value: 
+      then:
+        - component.update: sensor_hum_air_temperature
+        - component.update: sensor_hum_dew_point
+
+  # Selected Command Result - HUM
+  - platform: template
+    name: HUM - Command Result
+    id: result_hum
+    disabled_by_default: true
+
+button:
+  # Read HUM Sensor
+  - platform: template
+    name: HUM - Read
+    id: read_hum
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            id(hum_ezo).send_custom("R");
+
+  # Send Selected EZO Command - HUM
+  - platform: template
+    name: HUM - Command Send Selected
+    id: send_selected_hum
+    entity_category: "Config"
+    disabled_by_default: true
+    on_press:
+      then:
+        - lambda: |-
+            if (id(select_command_hum).state == "Read") {
+              id(hum_ezo).send_custom("R");
+            }
+            if (id(select_command_hum).state == "Information") {
+              id(hum_ezo).get_device_information();
+            }
+            if (id(select_command_hum).state == "Status") {
+              id(hum_ezo).send_custom("Status");
+            }
+            if (id(select_command_hum).state == "Get Enabled Parameter(s)") {
+              id(hum_ezo).send_custom("O,?");
+            }  
+            if (id(select_command_hum).state == "Output Units - Enable Humidity") {
+              id(hum_ezo).send_custom("O,HUM,1");
+            }
+            if (id(select_command_hum).state == "Output Units - Disable Humidity") {
+              id(hum_ezo).send_custom("O,HUM,0");
+            }
+            if (id(select_command_hum).state == "Output Units - Enable Temperature") {
+              id(hum_ezo).send_custom("O,T,1");
+            }
+            if (id(select_command_hum).state == "Output Units - Disable Temperature") {
+              id(hum_ezo).send_custom("O,T,0");
+            }
+            if (id(select_command_hum).state == "Output Units - Enable Dew Point") {
+              id(hum_ezo).send_custom("O,DEW,1");
+            }
+            if (id(select_command_hum).state == "Output Units - Disable Dew Point") {
+              id(hum_ezo).send_custom("O,DEW,0");
+            }
+            if (id(select_command_hum).state == "Check Calibration") {
+              id(hum_ezo).get_calibration();
+            }
+
+select:
+  - platform: template
+    name: HUM - Command Select
+    id: select_command_hum
     disabled_by_default: true
-    # on_custom: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_calibration: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_device_information: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_slope: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x);
-    # on_t: 
-    #   then:
-    #     - lambda: 
-    #         id(result_ph).publish_state(x); 
\ No newline at end of file
+    optimistic: true
+    entity_category: "Config"
+    options:
+      - "Read"
+      - "Information"
+      - "Status"
+      - "Get Enabled Parameter(s)"
+      - "Output Units - Enable Humidity"
+      - "Output Units - Disable Humidity"
+      - "Output Units - Enable Temperature"
+      - "Output Units - Disable Temperature"
+      - "Output Units - Enable Dew Point"
+      - "Output Units - Disable Dew Point"
+      - "Check Calibration"
+    initial_option: "Check Calibration"
+    set_action:
+      - logger.log:
+          format: "Chosen option: %s"
+          args: ["x.c_str()"]
\ No newline at end of file

From 9f72c558b8d6702019b7ed07bc91fe9748450660 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 15:48:16 -0500
Subject: [PATCH 21/26] add varaibles

---
 aquapi_config.yaml  | 3 +++
 common/ezo_co2.yaml | 2 +-
 common/ezo_ec.yaml  | 2 +-
 common/ezo_hum.yaml | 2 +-
 4 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 1c2013e..492cbf1 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -54,6 +54,7 @@ substitutions:
   update_ph: "60s"
   # EZO EC
   update_ec: "60s"
+  update_button_ec: "60s"
   # EZO DO
   update_do: "60s"
   # EZO RTD
@@ -62,8 +63,10 @@ substitutions:
   update_pmp: "60s"
   # EZO HUM
   update_hum: "60s"
+  update_button_hum: "60s"
   # EZO CO2
   update_co2: "60s"
+  update_button_co2: "60s"
 
 packages:
   device_base: !include common/device_base.yaml
diff --git a/common/ezo_co2.yaml b/common/ezo_co2.yaml
index 056f25c..a1f1e78 100644
--- a/common/ezo_co2.yaml
+++ b/common/ezo_co2.yaml
@@ -7,7 +7,7 @@ esphome:
 
 interval:
   # Update Raw CO2
-  - interval: "${update_co2}"
+  - interval: "${update_button_co2}"
     then:
       - button.press: read_co2
 
diff --git a/common/ezo_ec.yaml b/common/ezo_ec.yaml
index c9a2488..9276496 100644
--- a/common/ezo_ec.yaml
+++ b/common/ezo_ec.yaml
@@ -7,7 +7,7 @@ esphome:
 
 interval:
   # Update Raw EC
-  - interval: "${update_ec}"
+  - interval: "${update_button_ec}"
     then:
       - button.press: read_ec
 
diff --git a/common/ezo_hum.yaml b/common/ezo_hum.yaml
index 25138c7..a47a028 100644
--- a/common/ezo_hum.yaml
+++ b/common/ezo_hum.yaml
@@ -7,7 +7,7 @@ esphome:
 
 interval:
   # Update Raw HUM
-  - interval: "${update_hum}"
+  - interval: "${update_button_hum}"
     then:
       - button.press: read_hum
 

From e13b1884b8608e17539c04a4e04fc39ecd88daf8 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 15:51:31 -0500
Subject: [PATCH 22/26] Update ezo_co2.yaml

---
 common/ezo_co2.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/ezo_co2.yaml b/common/ezo_co2.yaml
index a1f1e78..cf57b9d 100644
--- a/common/ezo_co2.yaml
+++ b/common/ezo_co2.yaml
@@ -56,6 +56,7 @@ sensor:
     update_interval: "${update_co2}"
     state_class: "measurement"
     device_class: "temperature"
+    entity_category: "diagnostic"
     lambda: |-
       std::string str = id(raw_value_co2).state;
       std::vector<std::string> v;

From cf7ea53df99abd06fd077fc7d14d0aa2a4ffe89f Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 18:50:14 -0500
Subject: [PATCH 23/26] Update device_base.yaml

---
 common/device_base.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/device_base.yaml b/common/device_base.yaml
index 7e17d7f..692b6ea 100644
--- a/common/device_base.yaml
+++ b/common/device_base.yaml
@@ -89,7 +89,7 @@ sensor:
     id: i2c_devices
     icon: mdi:integrated-circuit-chip
     entity_category: "diagnostic"
-    disabled_by_default: true
+    # disabled_by_default: true
     lambda: |-
       byte error, address;
       int nDevices;

From 78134041d9b0d96d8bf077b5d96dbf96e92154e3 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 19:12:26 -0500
Subject: [PATCH 24/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 492cbf1..1a96b32 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -13,8 +13,8 @@ substitutions:
 
   # pins
   dallasPin: "16"
-  opticalHighPin: "33" # blue
   opticalLowPin: "32" # yellow
+  opticalHighPin: "33" # blue
   auxPin1: "26" # blue
   auxPin2: "27" # yellow
   sdaPin: "21" # blue

From 0ad9e8f570f550079de5845f65f573aee408ff77 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 19:13:15 -0500
Subject: [PATCH 25/26] Update aquapi_config.yaml

---
 aquapi_config.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/aquapi_config.yaml b/aquapi_config.yaml
index 1a96b32..96c16ca 100644
--- a/aquapi_config.yaml
+++ b/aquapi_config.yaml
@@ -8,7 +8,7 @@ substitutions:
   suffix: "true"
   # Import Config
   import_config: "false"
-  # Logger Level - Can use VERBOSE for more information
+  # Logger Level - Can use VERBOSE for more information in Logs
   logger: "DEBUG"
 
   # pins

From fa6d7dbd6e85659761c634d9577ecec261ae4842 Mon Sep 17 00:00:00 2001
From: Nick <nicholaswhite@capitalcityaquatics.com>
Date: Sun, 19 Nov 2023 20:16:21 -0500
Subject: [PATCH 26/26] Update ezo_hum.yaml

---
 common/ezo_hum.yaml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/common/ezo_hum.yaml b/common/ezo_hum.yaml
index a47a028..7b4383b 100644
--- a/common/ezo_hum.yaml
+++ b/common/ezo_hum.yaml
@@ -20,7 +20,7 @@ sensor:
     id: hum_ezo
     address: ${addHUM}
     unit_of_measurement: "%"
-    accuracy_decimals: 0
+    accuracy_decimals: 2
     update_interval: "${update_hum}"
     state_class: "measurement"
     device_class: "humidity"
@@ -173,6 +173,7 @@ button:
             }
 
 select:
+  # Select Command to Send
   - platform: template
     name: HUM - Command Select
     id: select_command_hum