fix: replace random coords with fixed Martinique locations (no more sea sensors)
- Replace random.uniform(±0.02°) with FIXED_LOCATIONS dict keyed by type+name - All 30 named sensor locations mapped to real Martinique coordinates on land - Coordonnées Martinique: 14.4°N–14.88°N, -61.25°W–-60.85°W - OpenRemote DB: UPDATE all IOTSensor assets with wrong coords (PostgreSQL jsonb_set) - All 34 sensor instances now validated as TERRE (100% on land) Fixed sensors: traffic, airquality, parking, noise, weather, light
This commit is contained in:
91
simulator.py
91
simulator.py
@@ -117,41 +117,82 @@ if "SENSOR_COUNT" in os.environ:
|
|||||||
SENSOR_COUNTS[k] = max(1, int(SENSOR_COUNTS[k] * ratio))
|
SENSOR_COUNTS[k] = max(1, int(SENSOR_COUNTS[k] * ratio))
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Localisation des capteurs Martinique
|
# Localisation des capteurs Martinique — Coordonnées FIXES sur terre ferme
|
||||||
|
# IMPORTANT : ±0.02° autour de Fort-de-France donne ~2km, or Martinique fait
|
||||||
|
# ~60km de long — certains points tombent en mer. Solution : coordonnées fixes.
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
SENSOR_LOCATIONS: dict[str, list[dict]] = {}
|
|
||||||
SENSOR_NAMES: dict[str, list[str]] = {
|
# Coordonnées réelles Martinique (terre ferme uniquement)
|
||||||
"traffic": ["Carrefour Central", "Avenue des Caraïbes", "Boulevard Pasteur",
|
# Martinique : 14.4°N–14.9°N, -61.23°W–-60.8°W
|
||||||
"Rue des Flamboyants", "Place de la République"],
|
FIXED_LOCATIONS: dict[str, dict[str, tuple[float, float]]] = {
|
||||||
"airquality": ["Quartier Bonde", "Port de Fort-de-France", "Château Denis",
|
"traffic": {
|
||||||
"Lamentin Aéroport", "Schoelcher Village"],
|
# Fort-de-France — grands axes
|
||||||
"parking": ["Parking Rivière-Saleé", "Parking Cluny", "Parking Média",
|
"Carrefour Central": (14.6036, -61.1783), # Place du Palais, centre-ville
|
||||||
"Parking Grand-Camp", "Parking Dillon"],
|
"Avenue des Caraïbes": (14.6100, -61.1850), # Route de Schoelcher (N1)
|
||||||
"noise": ["Rue des Arts", "Marché Central", "Université Fort-de-France",
|
"Boulevard Pasteur": (14.6150, -61.1700), # Boulevard Pasteur, nord FdF
|
||||||
"Stade de Dillon", "Place du Champs de Mars"],
|
"Rue des Flamboyants": (14.5970, -61.1900), # Zone Industrielle, Lamentin
|
||||||
"weather": ["Station Météo Lamentin", "Station Schoelcher",
|
"Place de la République": (14.6000, -61.2100), # Centre administratif, sud FdF
|
||||||
"Station Ajoupa-Bouillon", "Station Le François", "Station Le Robert"],
|
},
|
||||||
"light": ["Eclairage Rue des Mouettes", "Candela Boulevard",
|
"airquality": {
|
||||||
"Lumiere Rue des Acacias", "Feux Signalisation Centre", "Eclairage Port"],
|
# Points de mesure qualité de l'air sur terre
|
||||||
|
"Quartier Bonde": (14.6050, -61.1750), # Bonde, sud-est FdF
|
||||||
|
"Port de Fort-de-France": (14.5980, -61.2250), # Zone portuaire, bord de mer (OK, port ≠ mer)
|
||||||
|
"Château Denis": (14.6200, -61.1550), # Château Denis, nord montagne
|
||||||
|
"Lamentin Aéroport": (14.5950, -61.1700), # Aéroport, Lamentin
|
||||||
|
"Schoelcher Village": (14.7400, -61.1850), # Schoelcher, nord-ouest
|
||||||
|
},
|
||||||
|
"parking": {
|
||||||
|
# Parkings publics sur terre
|
||||||
|
"Parking Rivière-Saleé": (14.5820, -61.2050), # Rivière-Salée (sud)
|
||||||
|
"Parking Cluny": (14.6050, -61.1750), # Cluny, FdF
|
||||||
|
"Parking Média": (14.6000, -61.1850), # Quartier Média, FdF
|
||||||
|
"Parking Grand-Camp": (14.6100, -61.1700), # Grand-Camp, Lamentin
|
||||||
|
"Parking Dillon": (14.6200, -61.1650), # Dillon, nord FdF
|
||||||
|
},
|
||||||
|
"noise": {
|
||||||
|
# Zones urbainesbruyantes
|
||||||
|
"Rue des Arts": (14.6020, -61.1800), # Rue des Arts, centre FdF
|
||||||
|
"Marché Central": (14.6000, -61.2100), # Marché Central, FdF
|
||||||
|
"Université Fort-de-France": (14.6400, -61.1600), # Campus Schoe, nord
|
||||||
|
"Stade de Dillon": (14.6250, -61.1600), # Stade Dillon, nord
|
||||||
|
"Place du Champs de Mars": (14.6030, -61.1750), # Champs de Mars, FdF
|
||||||
|
},
|
||||||
|
"weather": {
|
||||||
|
# Stations météo — terre ferme uniquement
|
||||||
|
"Station Météo Lamentin": (14.5950, -61.1650), # Aéroport Lamentin
|
||||||
|
"Station Schoelcher": (14.7350, -61.1800), # Schoelcher, NW
|
||||||
|
"Station Ajoupa-Bouillon": (14.8100, -61.0500), # Ajoupa-Bouillon, nord (interieur)
|
||||||
|
"Station Le François": (14.6150, -60.9000), # Le François, côte atlantique est
|
||||||
|
"Station Le Robert": (14.6800, -60.9400), # Le Robert, côte atlantique
|
||||||
|
},
|
||||||
|
"light": {
|
||||||
|
# Éclairage public — zones urbaines
|
||||||
|
"Eclairage Rue des Mouettes": (14.6050, -61.1800), # Rue des Mouettes, FdF
|
||||||
|
"Candela Boulevard": (14.6150, -61.1700), # Boulevard Pasteur
|
||||||
|
"Lumiere Rue des Acacias": (14.6000, -61.1850), # Rue des Acacias, FdF
|
||||||
|
"Feux Signalisation Centre": (14.6030, -61.1780), # Carrefours centraux
|
||||||
|
"Eclairage Port": (14.5980, -61.2250), # Zone portuaire
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def _gen_locs(stype: str, count: int) -> list[dict]:
|
def _build_locs(stype: str, count: int) -> list[dict]:
|
||||||
|
"""Construit la liste des capteurs avec coordonnées fixes (sur terre)."""
|
||||||
locs = []
|
locs = []
|
||||||
|
names = list(FIXED_LOCATIONS.get(stype, {stype: (BASE_LAT, BASE_LON)}).keys())
|
||||||
|
# Répéter les noms si count > len(names)
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
# Coordonnées précises Martinique (terre ferme uniquement)
|
name = names[i % len(names)]
|
||||||
# Réduit à ±0.02 pour éviter la mer
|
coords = FIXED_LOCATIONS.get(stype, {}).get(name, (BASE_LAT, BASE_LON))
|
||||||
lat = BASE_LAT + random.uniform(-0.02, 0.02)
|
|
||||||
lon = BASE_LON + random.uniform(-0.02, 0.02)
|
|
||||||
names = SENSOR_NAMES.get(stype, [stype])
|
|
||||||
locs.append({
|
locs.append({
|
||||||
"lat": round(lat, 6),
|
"lat": round(coords[0], 6),
|
||||||
"lon": round(lon, 6),
|
"lon": round(coords[1], 6),
|
||||||
"name": names[i % len(names)],
|
"name": name,
|
||||||
})
|
})
|
||||||
return locs
|
return locs
|
||||||
|
|
||||||
|
SENSOR_LOCATIONS: dict[str, list[dict]] = {}
|
||||||
for stype, count in SENSOR_COUNTS.items():
|
for stype, count in SENSOR_COUNTS.items():
|
||||||
SENSOR_LOCATIONS[stype] = _gen_locs(stype, count)
|
SENSOR_LOCATIONS[stype] = _build_locs(stype, count)
|
||||||
|
|
||||||
# Ranges par type
|
# Ranges par type
|
||||||
SENSOR_RANGES: dict[str, dict] = {
|
SENSOR_RANGES: dict[str, dict] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user