import json import httpx from datetime import datetime, timedelta import math # Parameter - diese können später als Eingabe konfiguriert werden METER_NUMBER = "Any - Als Parameter" # Wird durch tatsächliche Zählernummer ersetzt CHART_TYPE = "line" # line, bar, area GROUP_BY = "hour" # hour, day, week INCLUDE_STATISTICS = True # GraphQL Queries FIND_SENSORS_QUERY = """ query FindSensors($meterNumber: String!) { sensorsForMeterNumber(meterNumber: $meterNumber) { sensorId sensorName sensorNameExtern descr measureConcept { id name descr } } } """ GET_VARIABLES_QUERY = """ query GetVariables($sensorId: ID!) { availableVariableUnits(sensorId: $sensorId) { variableUnitId variableName unitName } } """ FIND_OBSERVATIONS_QUERY = """ query FindObservations($measurementConceptId: ID!, $sensorName: String, $startTime: String, $endTime: String) { findObservation( measurementConceptId: $measurementConceptId sensorName: $sensorName startTime: $startTime endTime: $endTime ) { id moment value meterValue observationVariableUnit { observationVariable { name description } unit { name description } } quality } } """ def make_graphql_request(query, variables): """GraphQL Request ausführen""" try: with httpx.Client() as client: response = client.post( f"{EXTERNAL_BASE_URL}/graphql", headers=AUTH_HEADERS, json={"query": query, "variables": variables} ) response.raise_for_status() return response.json() except Exception as e: return {"errors": [str(e)]} def calculate_statistics(observations): """Berechnet Statistiken für die Messwerte""" if not observations: return {} values = [obs.get('value', 0) for obs in observations] meter_values = [obs.get('meterValue', 0) for obs in observations] return { 'total_readings': len(observations), 'value_min': min(values) if values else 0, 'value_max': max(values) if values else 0, 'value_avg': sum(values) / len(values) if values else 0, 'meter_min': min(meter_values) if meter_values else 0, 'meter_max': max(meter_values) if meter_values else 0, 'meter_avg': sum(meter_values) / len(meter_values) if meter_values else 0, 'consumption': max(meter_values) - min(meter_values) if meter_values else 0 } def format_datetime(dt_string): """Formatiert DateTime für Chart.js""" try: dt = datetime.fromisoformat(dt_string.replace('Z', '+00:00')) return dt.strftime('%Y-%m-%d %H:%M:%S') except: return dt_string # Hauptlogik result_html = "" try: # 1. Sensoren für Zählernummer finden sensors_response = make_graphql_request(FIND_SENSORS_QUERY, { "meterNumber": METER_NUMBER }) if "errors" in sensors_response: result = f"
Fehler beim Abrufen der Sensoren: {sensors_response['errors']}
" else: sensors = sensors_response.get('data', {}).get('sensorsForMeterNumber', []) if not sensors: result = f"
Keine Sensoren für Zählernummer '{METER_NUMBER}' gefunden.
" else: sensor = sensors[0] # Ersten Sensor verwenden sensor_id = sensor['sensorId'] sensor_name = sensor['sensorName'] measure_concept_id = sensor['measureConcept']['id'] # 2. Verfügbare Variablen abrufen variables_response = make_graphql_request(GET_VARIABLES_QUERY, { "sensorId": sensor_id }) available_vars = variables_response.get('data', {}).get('availableVariableUnits', []) # 3. Zeitraum: Letzten 3 Monate end_time = datetime.now() start_time = end_time - timedelta(days=90) # 4. Messwerte abrufen observations_response = make_graphql_request(FIND_OBSERVATIONS_QUERY, { "measurementConceptId": measure_concept_id, "sensorName": sensor_name, "startTime": start_time.isoformat(), "endTime": end_time.isoformat() }) observations = observations_response.get('data', {}).get('findObservation', []) # 5. Statistiken berechnen stats = calculate_statistics(observations) # 6. Daten für Chart vorbereiten chart_labels = [] chart_values = [] chart_meter_values = [] for obs in observations: chart_labels.append(format_datetime(obs['moment'])) chart_values.append(obs.get('value', 0)) chart_meter_values.append(obs.get('meterValue', 0)) # 7. HTML mit Chart.js generieren result_html = f""" Messwerte Dashboard - {sensor_name}

📊 Messwerte Dashboard

Sensor: {sensor_name} | Zählernummer: {METER_NUMBER}
Zeitraum: {start_time.strftime('%d.%m.%Y')} - {end_time.strftime('%d.%m.%Y')}
""" # Statistiken hinzufügen if INCLUDE_STATISTICS and stats: result_html += f"""
{stats['total_readings']:,}
Gesamte Messwerte
{stats['consumption']:,.2f}
Verbrauch (Differenz)
{stats['value_avg']:,.2f}
Ø Messwert
{stats['meter_max']:,.2f}
Max Zählerstand
""" # Chart hinzufügen result_html += f"""

Messwerte Verlauf ({CHART_TYPE.title()})

Zählerstände

Verfügbare Variablen:

    """ for var in available_vars: result_html += f"
  • {var['variableName']} ({var['unitName']})
  • " result_html += f"""

Anzahl Sensoren gefunden: {len(sensors)}

Measure Concept: {sensor['measureConcept']['name']}

""" result = result_html except Exception as e: result = f"
Allgemeiner Fehler: {str(e)}
" print(f"Generated HTML dashboard with {len(chart_labels) if 'chart_labels' in locals() else 0} data points")