Through some more poking and prodding with assistance from Gemini I found the flow rate. So my main.py code is now:
import requests
import time
import json
import sys
# --- CONFIGURATION ---
EBUSD_URL = "http://localhost:8080/data"
API_KEY = "[key removed!]"
EMONCMS_URL = "https://emoncms.org/input/post"
NODE_NAME = "vaillant"
INTERVAL = 30
# --- SENSORS MAP ---
SENSORS = {
# --- USER REQUESTED REGISTERS ---
"flow_temp": ("hmu", "RunDataFlowTemp"),
"return_temp": ("hmu", "RunDataReturnTemp"),
"inside_temp": ("basv", "Z1RoomTemp"),
# --- OTHER ESSENTIALS ---
"elec_power": ("hmu", "RunDataElectricPowerConsumption"),
"flow_rate": ("hmu", "BuildingCircuitFlow"), # Confirmed working
"env_yield": ("hmu", "CurrentYieldPower"), # Used for Heat Output calc
# --- AUXILIARY ---
"outside_temp": ("basv", "DisplayedOutsideTemp"),
"target_temp": ("basv", "Z1ActualRoomTempDesired"),
"dhw_temp": ("basv", "HwcStorageTemp"),
}
def fetch_value(circuit, name):
"""Fetches a value from ebusd."""
try:
# Force a fresh read (maxage=0) for dynamic data (Flow/Yield)
# Use cached (maxage=60) for Temps to save bus traffic
is_dynamic = (name in ["BuildingCircuitFlow", "CurrentYieldPower"])
maxage = "0" if is_dynamic else "60"
url = f"{EBUSD_URL}/{circuit}/{name}?def&maxage={maxage}"
r = requests.get(url, timeout=5)
if r.status_code != 200: return None
data = r.json()
# Recursive finder for "value"
def find_val_recursive(d):
if isinstance(d, dict):
if "value" in d:
v = d["value"]
if isinstance(v, (int, float)) and not isinstance(v, bool):
return float(v)
for item in d.values():
res = find_val_recursive(item)
if res is not None: return res
return None
return find_val_recursive(data)
except:
return None
def main():
print("--- Vaillant Bridge (Final Production) ---")
while True:
payload = {}
raw_data = {}
# 1. Fetch All Sensors
for key, (circuit, reg_name) in SENSORS.items():
val = fetch_value(circuit, reg_name)
if val is not None:
raw_data[key] = val
# Add to payload (except internal calc variables)
if key != "env_yield":
payload[key] = val
# 2. Calculate True Heat Output
# Total Heat = Environmental Yield (kW * 1000) + Electrical Input (W)
elec = raw_data.get("elec_power", 0.0)
env_yield_kw = raw_data.get("env_yield", 0.0)
if env_yield_kw > 0:
payload["heat_output"] = (env_yield_kw * 1000.0) + elec
else:
payload["heat_output"] = 0.0
# 3. Defaults
if "elec_power" not in payload: payload["elec_power"] = 0.0
# 4. Upload
if len(payload) > 1:
try:
params = {
"node": NODE_NAME,
"fulljson": json.dumps(payload),
"apikey": API_KEY
}
requests.post(EMONCMS_URL, params=params, timeout=10)
print(f"Uploaded: {payload}")
except Exception as e:
print(f"Upload failed: {e}")
else:
print("Waiting for valid data...")
sys.stdout.flush()
time.sleep(INTERVAL)
if __name__ == "__main__":
main()
This is run in a docker container as set out here. For how I went from this point to using the data on emonCMS .org and then on to heatpumpmonitor .org, see this post