Water softener (CLACK WS1) consumed m3/liter monitoring

Newbie here!
Here is my setup to monitor m3/liter continuously on the Clack WS1.
I am using the meter port (3 wires, red-black-white on the bottom right corner of the board), together with ESP32 module. I am using only the black wire (ground) and the white wire(signal). The signal has constant voltage of about 3.3v and when the water flow starts, it start pulsing (drops to 0v and then goes back up to 3.3v) depending of how fast the water flows. I figured (made measurements/calibration) that when 17 pulses has passed 1 liter of water is being pushed trough. I have a second Clack WS1 and it measures the same thing there as well. I connected the black wire to the ground of the ESP and white wire to pin 35. (powering the esp with external power supply). Here is the code for the ESP32:

#include <WiFi.h>
#include <HTTPClient.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#define water_pin 35
#define PULSES_PER_LITER 17
#define UPDATE_INTERVAL 60000  // 1 minute in milliseconds

int pulseCount = 0;
bool isLowVoltage = true;
float totalLiters = 0.0;
unsigned long lastUpdate = 0;

const char *ssid = "WiFi";
const char *password = "password";
const char *serverUrl = "http://10.1.1.151/water_meter.php";

void sendDataToServer(float liters) {
  // Check if liters is greater than 0 before sending to the server
  if (liters > 0.0) {
    HTTPClient http;

    // Prepare JSON payload
    String jsonData = "{\"liters\":" + String(liters, 3) + ", \"entity\":\"hallway\"}";


    // Send HTTP POST request to PHP script
    http.begin(serverUrl);
    http.addHeader("Content-Type", "application/json");
    int httpResponseCode = http.POST(jsonData);

    // Check for a successful response
    if (httpResponseCode == 200) {
      Serial.println("Data sent successfully");
    } else {
      Serial.print("HTTP Error code: ");
      Serial.println(httpResponseCode);
    }

    http.end();  // Close the connection
  }
}

void setup() {
  Serial.begin(115200);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Set totalLiters to 0 on startup
  totalLiters = 0.0;

  // Set the last update time
  lastUpdate = millis();

  // Configure OTA
  ArduinoOTA.setHostname("esp32-waterflow-hallway");
  ArduinoOTA.begin();
  ArduinoOTA.setPassword("");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // Handle OTA updates
  ArduinoOTA.handle();

  // Read the analog value from water_pin
  int analogValue = analogRead(water_pin);

  // Check if the analog value is zero
  if (analogValue == 0) {
    // If in a low voltage state, start a new pulse
    if (isLowVoltage) {
      pulseCount++;
      isLowVoltage = false;

      // Increment total liters for each pulse
      totalLiters += 1.0 / PULSES_PER_LITER;
      Serial.print("Total Liters: ");
      Serial.println(totalLiters, 3);
    }
  } else {
    // If the voltage is not zero and isLowVoltage was false, reset the flag
    if (!isLowVoltage) {
      isLowVoltage = true;
    }
  }

  // Check if it's time to update the database
  if (millis() - lastUpdate >= UPDATE_INTERVAL) {
    // Send data to server
    sendDataToServer(totalLiters);

    // Reset totalLiters
    totalLiters = 0.0;

    // Reset pulse count or perform any other actions needed before the next update

    // Set the last update time
    lastUpdate = millis();
  }

  delay(10);  // Optional delay to control the rate of analog readings
}

Let me briefly explain the code:
We are reading the pulses on the pin, collecting the data for 1 min, translating the pulses to liters, and then sending the data to a php file hosted on a local raspberry pi, after that the process starts over.
Here is how the php file looks like:

<?php
// Connect to MySQL
$host = 'localhost';
$dbname = 'db_name';
$username = 'username';
$password = 'password';

try {
    $db = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    // Set the PDO error mode to exception
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        // Retrieve the entity variable from the GET request
        $entity = isset($_GET['entity']) ? $_GET['entity'] : null;
        if ($entity=='') {
            http_response_code(400);
            echo json_encode(array('message' => 'Entity cannot be empty'));
            die();
        }
        // Handle GET request to retrieve data
        try {
            // Example SQL query to retrieve data for a specific entity
            $stmt = $db->prepare("SELECT FORMAT(SUM(liters), 3) AS total_liters FROM data WHERE DATE(date) = CURDATE() AND entity = :entity");
            $stmt->bindParam(':entity', $entity);

            $stmt->execute();

            // Fetch all rows as associative arrays
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Return the result as JSON
            echo json_encode($result);
        } catch (PDOException $e) {
            // Log the error and send a response with an error message
            http_response_code(500);
            echo json_encode(array('message' => 'Internal Server Error.'));
        }
    } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
        // Handle POST request to insert data
        $data = json_decode(file_get_contents("php://input"), true);
        
        
        if (isset($data['liters'])&& isset($data['entity'])) {
            $liters = $data['liters'];
            $entity = $data['entity'];

            // Begin a new transaction
            $db->beginTransaction();

            try {
                // Example SQL query to insert data
                $stmt = $db->prepare("INSERT INTO data (date, entity, liters) VALUES (NOW(), :entity, :liters)");
                $stmt->bindParam(':entity', $entity);
                $stmt->bindParam(':liters', $liters);

                // Execute the query
                $stmt->execute();

                // Commit the transaction
                $db->commit();

                echo json_encode(array('message' => 'Data inserted successfully'));
            } catch (PDOException $e) {
                // Rollback the transaction on error
                $db->rollBack();
                http_response_code(500);
                echo json_encode(array('message' => 'Internal Server Error.'));
            }
        } else {
            http_response_code(400);
            echo json_encode(array('message' => 'Bad request. Missing "liters" in the request.'));
        }
    } else {
        http_response_code(405); // Method Not Allowed
        echo json_encode(array('message' => 'Method not allowed.'));
    }
} catch (PDOException $e) {
    // Log the error and send a response with an error message
    http_response_code(500);
    echo json_encode(array('message' => 'Internal Server Error.'));
}

?>

I’ll explain briefly the php file. It gets the data from the ESP and stores it in a database. Also Serves the stored data to Home Assistant.

Here is HA setup:
In configuration.yaml I’ve added:

#Sensor for the water consumption in the hallway     
  - platform: rest
    name: Water Consumption Hallway
    resource: http://10.1.1.151/water_meter.php?entity=hallway
    value_template: "{{ value_json[0].total_liters | float }}"
    json_attributes:
      - entity
    unit_of_measurement: "L"
    scan_interval: 60  # Update every 60 seconds
    unique_id: sensor.water_consumption_hallway
    device_class: water
    state_class: total_increasing
#Sensor for the water consumption in the kitchen    
  - platform: rest
    name: Water Consumption Hallway
    resource: http://10.1.1.151/water_meter.php?entity=kitchen
    value_template: "{{ value_json[0].total_liters | float }}"
    json_attributes:
      - entity
    unit_of_measurement: "L"
    scan_interval: 65  # Update every 60 seconds
    unique_id: sensor.water_consumption_kitchen
    device_class: water
    state_class: total_increasing    
#Combine the two sensors    
  - platform: template
    sensors:
      total_water_consumption:
        friendly_name: "Total Water Consumption"
        value_template: "{{ states('sensor.water_consumption_kitchen') | float + states('sensor.water_consumption_hallway') | float }}"
        unit_of_measurement: "L"
        device_class: water
      total_water_cost:
        friendly_name: "Total Water Cost"
        value_template: "{{ ((states('sensor.water_consumption_kitchen') | float + states('sensor.water_consumption_hallway') | float) * 0.003498) | round(2) }}"
        unit_of_measurement: "BGN"
        device_class: water

p.s. 0.003498 is the cost for 1 liter of water where I live right now.

The sensor will also shows in the energy dashboard as well.
Here is the end result: