Kamstrup FlowIQ 2200

Also got it working!

TX has to be masked, as the signal is too “bright”. My solution for now: white electrical tape in front of the TX “hole”. Rx can stay as it is.

I will drop more details, as soon as the installation is finalized.

esphome:
  name: flowiq-2200
  friendly_name: flowIQ 2200

esp8266:
  board: esp01_1m

logger:
  baud_rate: 0

api:
  encryption:
    key: "your key"

ota:
  - platform: esphome
    password: "your password"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "Flowiq-2200 Fallback Hotspot"
    password: "12345678"

captive_portal:

mdns:
  disabled: false

web_server:
  port: 80

uart:
  baud_rate: 1200
  stop_bits: 2
  tx_pin: GPIO1
  rx_pin: GPIO3

sensor:
  - platform: kamstrup_kmp
    id: kamstrup_live
    update_interval: 120s
    custom:
      - name: Volume
        command: 0x0044 # reg 68
        unit_of_measurement: "m³"
        accuracy_decimals: 5
        state_class: "total_increasing"
        device_class: "water"

      #- name: Flow
      #  command: 0x004A # reg 74
      #  unit_of_measurement: "L/h"
      #  accuracy_decimals: 3
      #  state_class: "measurement"
      #  device_class: "volume_flow_rate"

      #- name: Water temperature
      #  command: 0x0124 # reg 292
      #  unit_of_measurement: "°C"
      #  accuracy_decimals: 2
      #  state_class: "measurement"
      #  device_class: "temperature"

      - name: Battery days left
        id: battery_days
        command: 0x0246 # reg 582
        unit_of_measurement: "days"
        accuracy_decimals: 1

  - platform: copy
    source_id: battery_days
    name: "Battery lifetime percent"
    unit_of_measurement: "%"
    accuracy_decimals: 1
    filters:
      - lambda: |-
          float pct = (x / (16.0 * 365.0)) * 100.0;
          if (pct < 0.0) return 0.0;
          if (pct > 100.0) return 100.0;
          return pct;

  - platform: copy
    source_id: battery_days
    name: "Battery lifetime decimal years"
    unit_of_measurement: "a"
    accuracy_decimals: 2
    filters:
      - lambda: return x / 365.0;

  - platform: wifi_signal
    name: "Diag : WiFi Signal dB"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: diagnostic

  - platform: copy
    source_id: wifi_signal_db
    name: "Diag : WiFi Signal Percent"
    unit_of_measurement: "%"
    entity_category: diagnostic
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);

button:
  - platform: restart
    name: "Ctrl : Device Restart"

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "Diag : IP Address"
    ssid:
      name: "Diag : Connected SSID"
    mac_address:
      name: "Diag : Mac Address"

  - platform: template
    name: "Battery lifetime Y/M/D"
    update_interval: 60s
    lambda: |-
      if (isnan(id(battery_days).state) || id(battery_days).state < 0) {
        return {"unknown"};
      }

      int total_days = (int) roundf(id(battery_days).state);

      int years = total_days / 365;
      int rem_days = total_days % 365;
      int months = rem_days / 30;
      int days = rem_days % 30;

      char buffer[32];
      sprintf(buffer, "%dJ %dM %dT", years, months, days);
      return {buffer};
1 Like