Fix simulator for cariflex.digitribe.fr domain - working ingestion

This commit is contained in:
Eric F
2026-06-08 22:03:47 -04:00
parent 11a51faffb
commit fa9381ba69
2 changed files with 348 additions and 54 deletions

View File

@@ -1,21 +1,15 @@
#!/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
"""Cariflex Simulator - Posts data to FlexMeasures via session cookies."""
import requests
import random
import math
from datetime import datetime, timezone, timedelta
from flexmeasures_client import FlexMeasuresClient
FM_HOST = "https://flexmeasures.digitribe.fr"
FM_HOST = "https://cariflex.digitribe.fr"
FM_EMAIL = "admin@digitribe.fr"
FM_PASSWORD = "Digitribe972"
with open("/tmp/fm_pass.txt") as f:
FM_PASSWORD=f.read().strip()
# 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}
@@ -27,7 +21,6 @@ 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:
@@ -54,57 +47,92 @@ def generate_value(cfg, hour):
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)
def main():
print(f"Cariflex Simulator -> {FM_HOST}", flush=True)
print(f" Sensors: {len(SENSORS)}", flush=True)
success = 0
failed = 0
# Create session with CSRF token handling
session = requests.Session()
session.verify = False # Self-signed cert
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}")
# Get login page to extract CSRF token
login_url = f"{FM_HOST}/login"
r = session.get(login_url)
print(f" Login page: {r.status_code}", flush=True)
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()
# Extract CSRF token
from html.parser import HTMLParser
class CSRFParser(HTMLParser):
def __init__(self):
super().__init__()
self.token = None
def handle_starttag(self, tag, attrs):
if tag == "input":
attrs = dict(attrs)
if attrs.get("name") == "csrf_token":
self.token = attrs.get("value")
client = FlexMeasuresClient(
email=FM_EMAIL,
password=FM_PASSWORD,
host="flexmeasures.digitribe.fr",
ssl=True,
request_timeout=60.0
)
parser = CSRFParser()
parser.feed(r.text)
csrf_token = parser.token
print(f" CSRF token: {csrf_token[:20] if csrf_token else 'NOT FOUND'}...", flush=True)
print("✅ Connected to FlexMeasures")
# Login
r = session.post(login_url, data={
"email": FM_EMAIL,
"password": FM_PASSWORD,
"csrf_token": csrf_token,
"remember": "y",
}, allow_redirects=True)
print(f" Login: {r.status_code} (url: {r.url})", flush=True)
# Check if logged in
if "dashboard" in r.url or "login" not in r.url:
print(f" Logged in successfully!", flush=True)
else:
print(f" WARNING: May not be logged in (url: {r.url})", flush=True)
# Post sensor data
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})")
hour = now.hour
await asyncio.sleep(30)
success = 0
failed = 0
for sensor_id, cfg in SENSORS.items():
value = generate_value(cfg, hour)
start = (now - timedelta(minutes=5)).isoformat()
try:
r = session.post(
f"{FM_HOST}/api/v3_0/sensors/{sensor_id}/data",
json={
"values": [value],
"start": start,
"duration": "PT5M",
"unit": cfg["unit"],
"type": "PostSensorDataRequest",
},
timeout=30,
)
if r.status_code in [200, 201]:
success += 1
else:
failed += 1
if failed <= 3:
print(f" Sensor {sensor_id}: HTTP {r.status_code} - {r.text[:100]}", flush=True)
except Exception as e:
failed += 1
if failed <= 3:
print(f" Sensor {sensor_id}: {e}", flush=True)
iteration += 1
print(f" Iteration {iteration}: {success} OK, {failed} failed (hour={hour})", flush=True)
import time
time.sleep(30)
if __name__ == "__main__":
asyncio.run(main())
main()