Ich wurde letzte Woche von meinen Stadtwerken spontan auf den Kamstrup flowIQ 2200 Wasserzähler umgestellt.
Damit musste natürlich auch eine neue Lösung zum Auslesen her.
Leider stellen meine Stadtwerke den AES-Key für das Auslesen über Funk nicht zur Verfügung.
Damit bleiben eigentlich nur zwei Optionen:
-
ESPCAM
-
IR Schnittstelle - inspiriert über diesen Beitrag
Ich habe mich für Letzteres entschieden und konnte erfolgreich einen IR Smart Meter Lesekopf umflashen.
Problem
Die Kommunikation schlug zunächst fehl mit:
Received invalid message (prefix mismatch received 0x80, expected 0x40)
Received invalid message (prefix mismatch received 0x00, expected 0x40)
Ursache
Die Ursache war ein zu starkes IR-Signal.
Der Lesekopf stammt ursprünglich aus dem Stromzähler-Bereich (SML/D0) und ist dafür relativ „aggressiv“ ausgelegt.
Beim Kamstrup führt das dazu, dass der Empfänger übersteuert und nur noch Müll empfängt.
Lösung
Ich habe den TX-Teil (IR-LED) einfach mit etwas weißem Isolierband abgeklebt, um das Signal zu dämpfen.
Danach lief die Kommunikation sofort stabil.
RX konnte unverändert bleiben.
Hinweis zur Batterielaufzeit
Das Auslesen über die IR-Schnittstelle hat einen direkten Einfluss auf die Batterielaufzeit des Zählers.
Laut Hersteller liegt die erwartete Lebensdauer bei ca. 16 Jahren – durch das regelmäßige Abfragen wird sich diese jedoch verkürzen.
Wie stark genau, lässt sich aktuell schwer abschätzen und muss über die Zeit beobachtet werden.
Aus diesem Grund habe ich:
-
das Abfrageintervall auf 120 Sekunden erhöht
-
zusätzliche Werte wie Durchfluss (L/h) und Temperatur deaktiviert
-
und bewusst Batteriedaten mit ausgegeben, um die Entwicklung im Blick zu behalten
Mechanik / Halterung
Der restliche Tag ging dann für eine passende Halterung drauf, damit der Sensor exakt positioniert ist.
Wichtig dabei:
-
Die optische Schnittstelle ist nur aktiv, wenn die Magnete korrekt positioniert sind
-
Der Magnetring des IR-Lesekopfs passt glücklicherweise genau
Ohne saubere Positionierung + Magnete funktioniert die Kommunikation nicht
Halterung
Link zur Halterung:
https://makerworld.com/en/models/2613834-iqflow-2200-water-meter-braket-fur-ir-sensor
ESPHome YAML
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};



