forked from flobz/psa_car_controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ecomix.py
121 lines (108 loc) · 4.67 KB
/
ecomix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from datetime import datetime, timedelta
from statistics import mean, StatisticsError
import xml.etree.cElementTree as ElT
import numbers
import requests
import reverse_geocode
from pytz import UTC
from requests import RequestException
from mylogger import logger
CO2_SIGNAL_REQ_INTERVAL = 600
CO2_SIGNAL_URL = "https://api.co2signal.com"
class Ecomix:
_cache = {}
co2_signal_key = None
@staticmethod
def get_data_france(start, end):
start_str = start.strftime("%d/%m/%Y")
end_str = end.strftime("%d/%m/%Y")
try:
res = requests.get(
f"https://eco2mix.rte-france.com/curves/eco2mixWeb?type=co2&&dateDeb={start_str}"
f"&dateFin={end_str}&mode=NORM",
headers={
"Origin": "https://www.rte-france.com",
"Referer": "https://www.rte-france.com/eco2mix/les-emissions-de-co2-par-kwh-produit-en-france",
}
)
except RequestException:
logger.exception("get_data_france: ")
return None
etree = ElT.fromstring(res.text)
period_start = (start.hour + int(start.minute / 30)) * 4
period_end = (end.hour + int(end.minute / 30)) * 4
valeurs = etree.iter("valeur")
co2_per_kw = []
valeur = next(valeurs)
while int(valeur.attrib["periode"]) != period_start:
valeur = next(valeurs)
while int(valeur.attrib["periode"]) != period_end:
co2_per_kw.append(int(valeur.text))
valeur = next(valeurs)
try:
return mean(co2_per_kw)
except StatisticsError:
return None
@staticmethod
def get_data_from_co2_signal(latitude, longitude, country_code_default):
if Ecomix.co2_signal_key is not None:
try:
now = datetime.utcnow().replace(tzinfo=UTC)
country_code = Ecomix.get_country(latitude, longitude, country_code_default)
assert country_code is not None
if country_code not in Ecomix._cache:
Ecomix._cache[country_code] = []
elif len(Ecomix._cache[country_code]) > 0 and \
(now - Ecomix._cache[country_code][-1][0]).total_seconds() < CO2_SIGNAL_REQ_INTERVAL:
return False
res = requests.get(CO2_SIGNAL_URL + "/v1/latest",
headers={"auth-token": Ecomix.co2_signal_key},
params={"countryCode": country_code})
data = res.json()
value = data["data"]["carbonIntensity"]
assert isinstance(value, numbers.Number)
Ecomix._cache[country_code].append([now, value])
return data["status"] == "ok"
except (AssertionError, NameError, KeyError):
logger.debug("ecomix:", exc_info=True)
return False
else:
return False
@staticmethod
def clean_cache():
max_date = datetime.utcnow().replace(tzinfo=UTC) - timedelta(days=1)
for country in Ecomix._cache:
Ecomix._cache[country][:] = [x for x in Ecomix._cache[country] if max_date < x[0]]
@staticmethod
def get_co2_from_signal_cache(start: datetime, end: datetime, country_code):
Ecomix.clean_cache()
co2_per_kw = []
for row in Ecomix._cache.get(country_code, []):
if start < row[0] < end:
co2_per_kw.append(row[1])
if len(co2_per_kw) == 0:
return None
return mean(co2_per_kw)
@staticmethod
def get_country(latitude, longitude, country_code_default):
try:
location = reverse_geocode.search([(latitude, longitude)])[0]
country_code = location["country_code"]
return country_code
except (UnicodeDecodeError, IndexError):
logger.error("Can't find country for %s %s", latitude, longitude)
# return None
country_code = country_code_default
logger.warning("Using country of origin : %s (wrong co2 when traveling abroad)", country_code)
return country_code
@staticmethod
def get_co2_per_kw(start: datetime, end: datetime, latitude, longitude, country_code_default):
co2_per_kw = None
country_code = Ecomix.get_country(latitude, longitude, country_code_default)
if country_code is None:
return None
if Ecomix.co2_signal_key is not None:
co2_per_kw = Ecomix.get_co2_from_signal_cache(start, end, country_code)
elif country_code == 'FR':
co2_per_kw = Ecomix.get_data_france(start, end)
return co2_per_kw