-
Notifications
You must be signed in to change notification settings - Fork 290
/
EmissionsFactors.ts
96 lines (84 loc) · 2.89 KB
/
EmissionsFactors.ts
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
/*
* © 2023 Thoughtworks, Inc.
*/
import fetch from 'node-fetch'
import { configLoader, Logger } from './index'
import { CloudConstantsEmissionsFactors } from '@cloud-carbon-footprint/core'
export type mappedRegionsToElectricityMapZones = {
[key: string]: string | null
}
export const zoneIntensityFactors: {
[key: string]: { [key: string]: number }
} = {}
export const getEmissionsFactors = async (
region: string,
dateTime: string,
emissionsFactors: CloudConstantsEmissionsFactors,
mappedRegionsToElectricityMapZones: mappedRegionsToElectricityMapZones,
logger: Logger,
): Promise<CloudConstantsEmissionsFactors> => {
const electricityMapsToken = configLoader().ELECTRICITY_MAPS_TOKEN
const electricityMapsZone: string = mappedRegionsToElectricityMapZones[region]
// if there is no zone for the region, or no token, return the default emissions factor
if (!electricityMapsToken || !electricityMapsZone) {
if (!electricityMapsZone) {
logger.warn(
`Electricity Maps zone not found for ${region}. Using default emissions factors.`,
)
}
return emissionsFactors
}
// if there is a cached value for the zone, return it
if (zoneIntensityFactors[dateTime]?.[electricityMapsZone]) {
return {
[region]: zoneIntensityFactors[dateTime][electricityMapsZone],
}
}
// if there is no cached value for the zone, make a request to electricity maps
let response
try {
response = await getElectricityMapsData(electricityMapsZone, dateTime)
} catch (e) {
throw new Error(
`Failed to get data from Electricity Maps. Reason ${e.message}.`,
)
}
// if there is no response, return the default emissions factor
if (!response?.carbonIntensity) {
// add a warning if there is no response
logger.warn(
`Electricity Maps zone data was not found for ${region}. Using default emissions factors.`,
)
return emissionsFactors
}
// cache the value for the zone
if (zoneIntensityFactors[dateTime]) {
// if there is a cached value for the date, add the new zone
zoneIntensityFactors[dateTime][electricityMapsZone] =
response.carbonIntensity / 1000
} else {
// if there is no cached value for the date, create a new entry
zoneIntensityFactors[dateTime] = {
[electricityMapsZone]: response.carbonIntensity / 1000,
}
}
return {
[region]: zoneIntensityFactors[dateTime][electricityMapsZone],
}
}
export const getElectricityMapsData = async (
electricityMapsZone: string,
dateTime: string,
): Promise<any> => {
try {
const url = `https://api.electricitymap.org/v3/carbon-intensity/past?zone=${electricityMapsZone}&datetime=${dateTime}`
const res = await fetch(url, {
headers: {
'auth-token': configLoader().ELECTRICITY_MAPS_TOKEN,
},
})
return await res.json()
} catch (e) {
throw new Error(`Electricity Maps request failed. Reason ${e.message}.`)
}
}