- 40 FlexMeasures assets (10 PV, 10 Bat, 10 Chg, 10 EV) - Geolocated on Martinique - Documentation: architecture, deployment, concepts - Standards: Flex Ready, S2, OpenADR, EPEX SPOT - R&D tools: HAMLET, OPLEM, lemlab - Map patch: Mapbox -> OpenStreetMap
97 lines
3.4 KiB
Python
97 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Re-localise les assets Cariflex sur la Martinique."""
|
|
import subprocess, random
|
|
|
|
def run_sql(query):
|
|
subprocess.run([
|
|
"docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures",
|
|
"-t", "-c", query
|
|
], capture_output=True, text=True)
|
|
|
|
# Martinique bounding box (approximate)
|
|
# Lat: 14.38 to 14.87, Lon: -61.25 to -60.82
|
|
# But we need to avoid the sea - use known land areas
|
|
|
|
# Realistic zones on Martinique (lat, lon) - major towns and industrial zones
|
|
ZONES = [
|
|
# Fort-de-France area (capital, dense urban)
|
|
(14.6091, -61.2155), # Fort-de-France center
|
|
(14.6150, -61.2080), # Fort-de-France north
|
|
(14.6050, -61.2200), # Fort-de-France south
|
|
(14.6200, -61.2000), # Fort-de-France east
|
|
(14.5950, -61.2100), # Fort-de-France west
|
|
# Le Lamentin (airport, industrial zone)
|
|
(14.6100, -61.0100), # Le Lamentin center
|
|
(14.6150, -61.0050), # Airport area
|
|
(14.6050, -61.0200), # Industrial zone
|
|
# Sainte-Marie (north-east)
|
|
(14.7800, -60.9800), # Sainte-Marie town
|
|
(14.7900, -60.9700), # North coast
|
|
# Le Robert (north-east coast)
|
|
(14.6800, -60.9400), # Le Robert town
|
|
# Le François (south-east coast)
|
|
(14.6600, -60.9000), # Le François town
|
|
# Le Vauclin (south-east tip)
|
|
(14.5500, -60.8400), # Le Vauclin
|
|
# Le Marin (south)
|
|
(14.4700, -60.8700), # Le Marin town
|
|
# Sainte-Anne (south coast)
|
|
(14.4400, -60.8500), # Sainte-Anne
|
|
# Le Diamant (south-west)
|
|
(14.4800, -61.0200), # Le Diamant
|
|
# Les Anses-d'Arlet (south-west coast)
|
|
(14.5000, -61.0800), # Les Anses-d'Arlet
|
|
# Sainte-Luce (south-east)
|
|
(14.4600, -60.9300), # Sainte-Luce
|
|
# Le Lorrain (north)
|
|
(14.7200, -60.9300), # Le Lorrain
|
|
]
|
|
|
|
random.seed(42) # Reproducible
|
|
|
|
# Shuffle zones and pick 10 for each asset type (with some overlap for co-location)
|
|
random.shuffle(ZONES)
|
|
|
|
# Get all assets ordered by type and name
|
|
result = subprocess.run([
|
|
"docker", "exec", "flexmeasures-db", "psql", "-U", "flexmeasures", "-d", "flexmeasures",
|
|
"-t", "-c", """
|
|
SELECT g.id, g.name, gt.name as type_name
|
|
FROM generic_asset g
|
|
JOIN generic_asset_type gt ON g.generic_asset_type_id = gt.id
|
|
ORDER BY gt.id, g.name;
|
|
"""
|
|
], capture_output=True, text=True)
|
|
|
|
assets = []
|
|
for line in result.stdout.strip().split('\n'):
|
|
parts = [p.strip() for p in line.split('|')]
|
|
if len(parts) == 3:
|
|
assets.append((int(parts[0]), parts[1], parts[2]))
|
|
|
|
# Assign random locations per type (4 types, 10 assets each)
|
|
type_groups = {}
|
|
for aid, name, atype in assets:
|
|
if atype not in type_groups:
|
|
type_groups[atype] = []
|
|
type_groups[atype].append((aid, name))
|
|
|
|
zone_idx = 0
|
|
for atype, group in type_groups.items():
|
|
# Pick 10 random zones for this type (zones can repeat slightly for density)
|
|
type_zones = [ZONES[i % len(ZONES)] for i in range(zone_idx, zone_idx + 10)]
|
|
random.shuffle(type_zones)
|
|
zone_idx += 10
|
|
|
|
for i, (aid, name) in enumerate(group):
|
|
lat, lon = type_zones[i]
|
|
# Add small random jitter (±0.005 degrees ≈ 500m)
|
|
lat += random.uniform(-0.005, 0.005)
|
|
lon += random.uniform(-0.005, 0.005)
|
|
|
|
run_sql("UPDATE generic_asset SET latitude = {}, longitude = {} WHERE id = {};".format(
|
|
round(lat, 6), round(lon, 6), aid))
|
|
print(" {} ({}) -> {:.4f}, {:.4f}".format(name, atype[:3], lat, lon))
|
|
|
|
print("\nDone!")
|