Grafana dashboard flexibilite/agregation
This commit is contained in:
165
scripts/inject_weather_prices.py
Normal file
165
scripts/inject_weather_prices.py
Normal file
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Cariflex - Injecte les données météo réelles et prix DSO simulés."""
|
||||
|
||||
import json
|
||||
import requests
|
||||
import re
|
||||
import warnings
|
||||
import random
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import pytz
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
FM_HOST = "https://cariflex.digitribe.fr"
|
||||
CREDS_FILE = "/tmp/fm_creds.json"
|
||||
MARTINIQUE_TZ = pytz.timezone("America/Martinique")
|
||||
|
||||
with open(CREDS_FILE) as f:
|
||||
creds = json.load(f)
|
||||
|
||||
session = requests.Session()
|
||||
session.verify = False
|
||||
|
||||
# Login
|
||||
r = session.get(f"{FM_HOST}/login")
|
||||
match = re.search(r'<input[^>]*csrf_token[^>]*value="([^"]+)"', r.text)
|
||||
csrf = match.group(1)
|
||||
r = session.post(f"{FM_HOST}/login", data={
|
||||
"email": creds["email"], "password": creds["password"],
|
||||
"csrf_token": csrf, "remember": "y"
|
||||
}, allow_redirects=True)
|
||||
print(f"Login: {'OK' if 'dashboard' in r.url else 'FAILED'}")
|
||||
|
||||
# Get existing sensors
|
||||
r = session.get(f"{FM_HOST}/api/v3_0/sensors")
|
||||
sensors = {}
|
||||
if r.status_code == 200:
|
||||
for s in r.json():
|
||||
sensors[s["name"]] = s["id"]
|
||||
print(f" Sensor: {s['id']} - {s['name']} (asset {s.get('generic_asset_id', '?')})")
|
||||
|
||||
# ========================================
|
||||
# 1. Injecter les prévisions météo réelles
|
||||
# ========================================
|
||||
print("\n=== Injection des données météo ===")
|
||||
|
||||
LAT, LON = 14.6091, -61.2155
|
||||
now_local = datetime.now(MARTINIQUE_TZ)
|
||||
today = now_local.strftime("%Y-%m-%d")
|
||||
|
||||
url = (
|
||||
f"https://api.open-meteo.com/v1/forecast?"
|
||||
f"latitude={LAT}&longitude={LON}"
|
||||
f"&hourly=shortwave_radiation,temperature_2m,wind_speed_10m"
|
||||
f"&timezone=America/Martinique"
|
||||
f"&start_date={today}&end_date={today}"
|
||||
)
|
||||
|
||||
try:
|
||||
resp = requests.get(url, timeout=15)
|
||||
if resp.status_code == 200:
|
||||
wdata = resp.json()
|
||||
hourly = wdata["hourly"]
|
||||
times = hourly["time"]
|
||||
irradiance = hourly["shortwave_radiation"]
|
||||
temperature = hourly["temperature_2m"]
|
||||
wind_speed = hourly["wind_speed_10m"]
|
||||
|
||||
print(f" Données météo récupérées: {len(times)} heures")
|
||||
|
||||
# Map sensor names to data
|
||||
sensor_data_map = {
|
||||
"irradiance": (irradiance, "W/m²"),
|
||||
"temperature": (temperature, "°C"),
|
||||
"wind_speed": (wind_speed, "m/s"),
|
||||
}
|
||||
|
||||
for sensor_name, (data, unit) in sensor_data_map.items():
|
||||
if sensor_name not in sensors:
|
||||
print(f" Sensor '{sensor_name}' non trouvé, ignoré")
|
||||
continue
|
||||
|
||||
sensor_id = sensors[sensor_name]
|
||||
posted = 0
|
||||
|
||||
for i, t in enumerate(times):
|
||||
dt = datetime.fromisoformat(t)
|
||||
value = max(0, data[i]) if data[i] is not None else 0
|
||||
|
||||
r = session.post(
|
||||
f"{FM_HOST}/api/v3_0/sensors/{sensor_id}/data",
|
||||
json={
|
||||
"values": [round(value, 1)],
|
||||
"start": dt.isoformat(),
|
||||
"duration": "PT1H",
|
||||
"unit": unit
|
||||
},
|
||||
timeout=30
|
||||
)
|
||||
if r.status_code in [200, 201, 202]:
|
||||
posted += 1
|
||||
|
||||
print(f" Sensor '{sensor_name}' (ID {sensor_id}): {posted}/{len(times)} values posted")
|
||||
else:
|
||||
print(f" Erreur API météo: HTTP {resp.status_code}")
|
||||
except Exception as e:
|
||||
print(f" Erreur récupération météo: {e}")
|
||||
|
||||
# ========================================
|
||||
# 2. Injecter les prix DSO simulés
|
||||
# ========================================
|
||||
print("\n=== Injection des prix DSO ===")
|
||||
|
||||
if "consumption_price" in sensors and "production_price" in sensors:
|
||||
consumption_price_id = sensors["consumption_price"]
|
||||
production_price_id = sensors["production_price"]
|
||||
|
||||
now_utc = datetime.now(timezone.utc)
|
||||
posted = 0
|
||||
|
||||
for hour in range(24):
|
||||
dt = now_utc - timedelta(hours=23-hour)
|
||||
hour_of_day = dt.hour
|
||||
|
||||
# Price pattern: peak during day, lower at night
|
||||
if 6 <= hour_of_day <= 22:
|
||||
consumption_price = round(random.uniform(80, 150), 2)
|
||||
production_price = round(random.uniform(60, 120), 2)
|
||||
else:
|
||||
consumption_price = round(random.uniform(40, 80), 2)
|
||||
production_price = round(random.uniform(30, 60), 2)
|
||||
|
||||
# Post consumption price
|
||||
r = session.post(
|
||||
f"{FM_HOST}/api/v3_0/sensors/{consumption_price_id}/data",
|
||||
json={
|
||||
"values": [consumption_price],
|
||||
"start": dt.isoformat(),
|
||||
"duration": "PT1H",
|
||||
"unit": "EUR/MWh"
|
||||
},
|
||||
timeout=30
|
||||
)
|
||||
if r.status_code in [200, 201, 202]:
|
||||
posted += 1
|
||||
|
||||
# Post production price
|
||||
r = session.post(
|
||||
f"{FM_HOST}/api/v3_0/sensors/{production_price_id}/data",
|
||||
json={
|
||||
"values": [production_price],
|
||||
"start": dt.isoformat(),
|
||||
"duration": "PT1H",
|
||||
"unit": "EUR/MWh"
|
||||
},
|
||||
timeout=30
|
||||
)
|
||||
if r.status_code in [200, 201, 202]:
|
||||
posted += 1
|
||||
|
||||
print(f" Prix DSO injectés: {posted} values")
|
||||
else:
|
||||
print(" Sensors de prix non trouvés")
|
||||
|
||||
print("\n=== Injection terminée ===")
|
||||
Reference in New Issue
Block a user