Skip to content

Commit 2890d43

Browse files
committed
Refactor to use new electricitymaps API endpoints
1 parent 4ef09d9 commit 2890d43

File tree

4 files changed

+23
-32
lines changed

4 files changed

+23
-32
lines changed

simvue/eco/api_client.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,33 @@
1919
import geocoder.location
2020
import typing
2121

22-
CO2_SIGNAL_API_ENDPOINT: str = "https://api.co2signal.com/v1/latest"
22+
CO2_SIGNAL_API_ENDPOINT: str = (
23+
"https://api.electricitymap.org/v3/carbon-intensity/latest"
24+
)
2325

2426

2527
class CO2SignalData(pydantic.BaseModel):
2628
datetime: datetime.datetime
2729
carbon_intensity: float
28-
fossil_fuel_percentage: float
2930

3031

3132
class CO2SignalResponse(pydantic.BaseModel):
32-
disclaimer: str
3333
country_code: str
34-
status: str
3534
data: CO2SignalData
3635
carbon_intensity_units: str
3736

3837
@classmethod
3938
def from_json_response(cls, json_response: dict) -> "CO2SignalResponse":
40-
_data: dict[str, typing.Any] = json_response["data"]
4139
_co2_signal_data = CO2SignalData(
4240
datetime=datetime.datetime.fromisoformat(
43-
_data["datetime"].replace("Z", "+00:00")
41+
json_response["datetime"].replace("Z", "+00:00")
4442
),
45-
carbon_intensity=_data["carbonIntensity"],
46-
fossil_fuel_percentage=_data["fossilFuelPercentage"],
43+
carbon_intensity=json_response["carbonIntensity"],
4744
)
4845
return cls(
49-
disclaimer=json_response["_disclaimer"],
50-
country_code=json_response["countryCode"],
51-
status=json_response["status"],
46+
country_code=json_response["zone"],
5247
data=_co2_signal_data,
53-
carbon_intensity_units=json_response["units"]["carbonIntensity"],
48+
carbon_intensity_units="gCO2e/kWh",
5449
)
5550

5651

@@ -109,16 +104,14 @@ def _get_user_location_info(self) -> None:
109104
def get(self) -> CO2SignalResponse:
110105
"""Get the current data"""
111106
_params: dict[str, float | str] = {
112-
"lat": self._latitude,
113-
"lon": self._longitude,
114-
"countryCode": self._two_letter_country_code,
107+
"zone": self._two_letter_country_code,
115108
}
116109

117110
if self.co2_api_token:
118111
_params["auth-token"] = self.co2_api_token.get_secret_value()
119112

120113
self._logger.debug(f"🍃 Retrieving carbon intensity data for: {_params}")
121-
_response = requests.get(f"{self.co2_api_endpoint}", params=_params)
114+
_response = requests.get(f"{self.co2_api_endpoint}", headers=_params)
122115

123116
if _response.status_code != http.HTTPStatus.OK:
124117
try:

simvue/eco/emissions_monitor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class CO2Monitor(pydantic.BaseModel):
5252

5353
def now(self) -> str:
5454
"""Return data file timestamp for the current time"""
55-
_now: datetime.datetime = datetime.datetime.now(datetime.UTC)
55+
_now: datetime.datetime = datetime.datetime.now(datetime.timezone.utc)
5656
return _now.strftime(TIME_FORMAT)
5757

5858
@property
@@ -187,7 +187,7 @@ def check_refresh(self) -> bool:
187187
with self._data_file_path.open("r") as in_f:
188188
self._local_data = json.load(in_f)
189189

190-
if not self._client or not self._local_data:
190+
if not self._client:
191191
return False
192192

193193
if (

tests/conftest.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,14 @@ def clear_out_files() -> None:
5353
@pytest.fixture
5454
def mock_co2_signal(monkeypatch: monkeypatch.MonkeyPatch) -> dict[str, dict | str]:
5555
_mock_data = {
56-
"data": {
57-
"datetime": datetime.datetime.now().isoformat(),
58-
"carbonIntensity": 40,
59-
"fossilFuelPercentage": 39,
60-
},
61-
"_disclaimer": "test disclaimer",
62-
"countryCode": "GB",
63-
"status": "unknown",
64-
"units": {"carbonIntensity": "eqCO2kg/kwh"}
56+
"zone":"GB",
57+
"carbonIntensity":85,
58+
"datetime":"2025-04-04T12:00:00.000Z",
59+
"updatedAt":"2025-04-04T11:41:12.947Z",
60+
"createdAt":"2025-04-01T12:43:58.056Z",
61+
"emissionFactorType":"lifecycle",
62+
"isEstimated":True,
63+
"estimationMethod":"TIME_SLICER_AVERAGE"
6564
}
6665
class MockCo2SignalAPIResponse:
6766
def json(*_, **__) -> dict:

tests/unit/test_ecoclient.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ def test_api_client_get_loc_info(mock_co2_signal) -> None:
1818
def test_api_client_query(mock_co2_signal: dict[str, dict | str]) -> None:
1919
_client = sv_eco_api.APIClient()
2020
_response: sv_eco_api.CO2SignalResponse = _client.get()
21-
assert _response.carbon_intensity_units == mock_co2_signal["units"]["carbonIntensity"]
22-
assert _response.country_code == mock_co2_signal["countryCode"]
23-
assert _response.data.carbon_intensity == mock_co2_signal["data"]["carbonIntensity"]
24-
assert _response.data.fossil_fuel_percentage == mock_co2_signal["data"]["fossilFuelPercentage"]
21+
assert _response.carbon_intensity_units == "gCO2e/kWh"
22+
assert _response.country_code == mock_co2_signal["zone"]
23+
assert _response.data.carbon_intensity == mock_co2_signal["carbonIntensity"]
2524

2625

2726
@pytest.mark.eco
@@ -41,7 +40,7 @@ def test_outdated_data_check(
4140
thermal_design_power_per_cpu=80,
4241
thermal_design_power_per_gpu=130,
4342
local_data_directory=tempd,
44-
intensity_refresh_interval=1 if refresh else 2,
43+
intensity_refresh_interval=1 if refresh else None,
4544
co2_intensity=None,
4645
co2_signal_api_token=None
4746
)

0 commit comments

Comments
 (0)