#!/usr/bin/env python3 """ Cariflex Simulator - Publishes simulated data to FlexMeasures API. Uses flexmeasures_client for authentication and data posting. Simulates 40 assets: 10 PV, 10 Battery, 10 EV Charger, 10 EV V2G """ import asyncio import time import random import math from datetime import datetime, timezone, timedelta from flexmeasures_client import FlexMeasuresClient FM_HOST = "https://flexmeasures.digitribe.fr" FM_EMAIL = "admin@digitribe.fr" FM_PASSWORD = "Digitribe972" # Sensor mapping: sensor_id -> (name, type, unit, min, max) SENSORS = {} for i in range(1, 11): SENSORS[40 + i] = {"name": f"pv_{i:02d}_power", "type": "pv", "unit": "kW", "min": 0, "max": 5} for i in range(1, 11): SENSORS[50 + i] = {"name": f"bat_{i:02d}_power", "type": "battery", "unit": "kWh", "min": 10, "max": 100} for i in range(1, 11): SENSORS[60 + i] = {"name": f"chg_{i:02d}_power", "type": "ev_charger", "unit": "kW", "min": 0, "max": 22} for i in range(1, 11): SENSORS[70 + i] = {"name": f"ev_{i:02d}_power", "type": "ev_v2g", "unit": "kWh", "min": 15, "max": 75} def generate_value(cfg, hour): """Generate realistic value based on asset type and time of day.""" t = cfg["type"] if t == "pv": if 6 <= hour <= 18: factor = max(0, math.sin((hour - 6) * math.pi / 12)) else: factor = 0 return round(max(0, cfg["max"] * factor + random.gauss(0, 0.3)), 2) elif t == "battery": base = 50 + 30 * math.sin((hour - 6) * math.pi / 12) return round(max(cfg["min"], min(cfg["max"], base + random.gauss(0, 2))), 2) elif t == "ev_charger": if 8 <= hour <= 22: factor = random.uniform(0.2, 1.0) else: factor = random.uniform(0, 0.15) return round(max(0, cfg["max"] * factor + random.gauss(0, 0.5)), 2) elif t == "ev_v2g": if 0 <= hour <= 6: base = 60 elif 17 <= hour <= 21: base = 30 else: base = 45 return round(max(cfg["min"], min(cfg["max"], base + random.gauss(0, 3))), 2) return 0 async def post_all_data(client): """Post data for all 40 sensors.""" now = datetime.now(timezone.utc) hour = now.hour start = now - timedelta(minutes=5) success = 0 failed = 0 for sensor_id, cfg in SENSORS.items(): value = generate_value(cfg, hour) try: await client.post_sensor_data( sensor_id=sensor_id, values=[value], start=start.isoformat(), duration="PT5M", unit=cfg["unit"] ) success += 1 except Exception as e: failed += 1 if failed <= 3: print(f" ⚠️ Sensor {sensor_id}: {e}") return success, failed async def main(): print("🚗 Cariflex Simulator → FlexMeasures API") print(f" Sensors: {len(SENSORS)} (10 PV, 10 Bat, 10 Chg, 10 EV)") print(f" FM API: {FM_HOST}") print() client = FlexMeasuresClient( email=FM_EMAIL, password=FM_PASSWORD, host="flexmeasures.digitribe.fr", ssl=True, request_timeout=60.0 ) print("✅ Connected to FlexMeasures") iteration = 0 while True: success, failed = await post_all_data(client) iteration += 1 now = datetime.now(timezone.utc) print(f" 📊 Iteration {iteration}: {success} OK, {failed} failed (hour={now.hour})") await asyncio.sleep(30) if __name__ == "__main__": asyncio.run(main())