UNPKG

if-electricitymaps

Version:

Electricity Maps plugin for Impact Framework.

101 lines 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElectricityMapsCarbonIntensity = void 0; const dayjs = require("dayjs"); const helpers_1 = require("../util/helpers"); const schemas_1 = require("../util/schemas"); const electricitymaps_api_1 = require("./electricitymaps-api"); const zod_1 = require("zod"); const utils_1 = require("@grnsft/if-core/utils"); const { InputValidationError } = utils_1.ERRORS; const ElectricityMapsCarbonIntensity = () => { const metadata = {}; const api = (0, electricitymaps_api_1.ElectricityMapsAPI)(); const errorBuilder = (0, helpers_1.buildErrorMessage)(exports.ElectricityMapsCarbonIntensity.name); /** * Test and init authentication by making a test request to EMaps API. */ const initializeAuthentication = async () => { await api.authenticate(); }; /** * Ensure inputs are valid. */ const validateInputs = (inputs) => { const inputsSchema = zod_1.z.array(schemas_1.inputSchema); try { inputsSchema.parse(inputs); } catch (error) { if (error instanceof zod_1.ZodError) { error.errors.map(e => { throw new InputValidationError(errorBuilder({ message: e.message, scope: 'input', })); }); } else { throw error; } } }; const execute = async (inputs) => { await initializeAuthentication(); validateInputs(inputs); const result = []; for await (const input of inputs) { let unit = 'gCO2eq/kWh'; let powerConsumption = input.power_consumption; if (!input.power_consumption) { powerConsumption = 1; unit = 'gCO2eq'; } const start = dayjs(input.timestamp); const end = start.add(input.duration, 'second'); const carbonIntensityParams = input.zone ? { zone: input.zone, start: start.toISOString(), end: end.toISOString(), } : { lon: input.longitude, lat: input.latitude, start: start.toISOString(), end: end.toISOString(), }; const carbonIntensities = api.getCarbonIntensity(carbonIntensityParams); const numHours = Math.floor(input.duration / 3600); const blocks = [...Array(numHours).keys()]; // For each full hour, calculate the ratio of the hour that is in the block const hourlyRatios = blocks.map(hour => { // This is the first hourly block, the ratio is the time between the start and the next hour. if (hour === 0) { return (start.add(1, 'hour').startOf('hour').diff(start, 'second') / 3600); } // This is the last hourly block, the ratio is the time between the start of the hour and the end. if (hour === numHours - 1) { return (end.diff(start.add(hour, 'hour').startOf('hour'), 'second') / 3600); } return 1; }); const totalCarbonIntensity = await carbonIntensities.then(intensities => intensities.reduce((memo, ci, index) => { memo += ci.value * hourlyRatios[index]; return memo; }, 0)); result.push({ ...input, carbonIntensity: totalCarbonIntensity * powerConsumption, unit: unit, }); } return result; }; return { metadata, execute, }; }; exports.ElectricityMapsCarbonIntensity = ElectricityMapsCarbonIntensity; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2VsZWN0cmljaXR5bWFwcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsNkNBQWtEO0FBQ2xELDZDQUE0QztBQUM1QywrREFBeUQ7QUFFekQsNkJBQWdDO0FBQ2hDLGlEQUE2QztBQUM3QyxNQUFNLEVBQUMsb0JBQW9CLEVBQUMsR0FBRyxjQUFNLENBQUM7QUFJL0IsTUFBTSw4QkFBOEIsR0FBRyxHQUFvQixFQUFFO0lBQ2xFLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNwQixNQUFNLEdBQUcsR0FBRyxJQUFBLHdDQUFrQixHQUFFLENBQUM7SUFDakMsTUFBTSxZQUFZLEdBQUcsSUFBQSwyQkFBaUIsRUFBQyxzQ0FBOEIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1RTs7T0FFRztJQUNILE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDMUMsTUFBTSxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDM0IsQ0FBQyxDQUFDO0lBRUY7O09BRUc7SUFDSCxNQUFNLGNBQWMsR0FBRyxDQUFDLE1BQXNCLEVBQUUsRUFBRTtRQUNoRCxNQUFNLFlBQVksR0FBRyxPQUFDLENBQUMsS0FBSyxDQUFDLHFCQUFXLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUM7WUFDSCxZQUFZLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksY0FBUSxFQUFFLENBQUM7Z0JBQzlCLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNuQixNQUFNLElBQUksb0JBQW9CLENBQzVCLFlBQVksQ0FBQzt3QkFDWCxPQUFPLEVBQUUsQ0FBQyxDQUFDLE9BQU87d0JBQ2xCLEtBQUssRUFBRSxP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LEVBQUUsS0FBSyxFQUFFLEVBQUU7Z0JBQ3JDLElBQUksSUFBSSxFQUFFLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkMsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQ04sQ0FBQztZQUVGLE1BQU0sQ0FBQyxJQUFJLENBQUM7Z0JBQ1YsR0FBRyxLQUFLO2dCQUNSLGVBQWUsRUFBRSxvQkFBb0IsR0FBRyxnQkFBZ0I7Z0JBQ3hELElBQUksRUFBRSxJQUFJO2FBQ1gsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUMsQ0FBQztJQUVGLE9BQU87UUFDTCxRQUFRO1FBQ1IsT0FBTztLQUNSLENBQUM7QUFDSixDQUFDLENBQUM7QUE1R1csUUFBQSw4QkFBOEIsa0NBNEd6QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGRheWpzIGZyb20gJ2RheWpzJztcbmltcG9ydCB7YnVpbGRFcnJvck1lc3NhZ2V9IGZyb20gJy4uL3V0aWwvaGVscGVycyc7XG5pbXBvcnQge2lucHV0U2NoZW1hfSBmcm9tICcuLi91dGlsL3NjaGVtYXMnO1xuaW1wb3J0IHtFbGVjdHJpY2l0eU1hcHNBUEl9IGZyb20gJy4vZWxlY3RyaWNpdHltYXBzLWFwaSc7XG5cbmltcG9ydCB7eiwgWm9kRXJyb3J9IGZyb20gJ3pvZCc7XG5pbXBvcnQge0VSUk9SU30gZnJvbSAnQGdybnNmdC9pZi1jb3JlL3V0aWxzJztcbmNvbnN0IHtJbnB1dFZhbGlkYXRpb25FcnJvcn0gPSBFUlJPUlM7XG5cbmltcG9ydCB7UGx1Z2luUGFyYW1zLCBQbHVnaW5JbnRlcmZhY2V9IGZyb20gJ0Bncm5zZnQvaWYtY29yZS90eXBlcyc7XG5cbmV4cG9ydCBjb25zdCBFbGVjdHJpY2l0eU1hcHNDYXJib25JbnRlbnNpdHkgPSAoKTogUGx1Z2luSW50ZXJmYWNlID0+IHtcbiAgY29uc3QgbWV0YWRhdGEgPSB7fTtcbiAgY29uc3QgYXBpID0gRWxlY3RyaWNpdHlNYXBzQVBJKCk7XG4gIGNvbnN0IGVycm9yQnVpbGRlciA9IGJ1aWxkRXJyb3JNZXNzYWdlKEVsZWN0cmljaXR5TWFwc0NhcmJvbkludGVuc2l0eS5uYW1lKTtcblxuICAvKipcbiAgICogVGVzdCBhbmQgaW5pdCBhdXRoZW50aWNhdGlvbiBieSBtYWtpbmcgYSB0ZXN0IHJlcXVlc3QgdG8gRU1hcHMgQVBJLlxuICAgKi9cbiAgY29uc3QgaW5pdGlhbGl6ZUF1dGhlbnRpY2F0aW9uID0gYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGFwaS5hdXRoZW50aWNhdGUoKTtcbiAgfTtcblxuICAvKipcbiAgICogRW5zdXJlIGlucHV0cyBhcmUgdmFsaWQuXG4gICAqL1xuICBjb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFBsdWdpblBhcmFtc1tdKSA9PiB7XG4gICAgY29uc3QgaW5wdXRzU2NoZW1hID0gei5hcnJheShpbnB1dFNjaGVtYSk7XG4gICAgdHJ5IHtcbiAgICAgIGlucHV0c1NjaGVtYS5wYXJzZShpbnB1dHMpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBab2RFcnJvcikge1xuICAgICAgICBlcnJvci5lcnJvcnMubWFwKGUgPT4ge1xuICAgICAgICAgIHRocm93IG5ldyBJbnB1dFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgICAgIGVycm9yQnVpbGRlcih7XG4gICAgICAgICAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgICAgICAgICAgc2NvcGU6ICdpbnB1dCcsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGV4ZWN1dGUgPSBhc3luYyAoaW5wdXRzOiBQbHVnaW5QYXJhbXNbXSk6IFByb21pc2U8UGx1Z2luUGFyYW1zW10+ID0+IHtcbiAgICBhd2FpdCBpbml0aWFsaXplQXV0aGVudGljYXRpb24oKTtcbiAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIGF3YWl0IChjb25zdCBpbnB1dCBvZiBpbnB1dHMpIHtcbiAgICAgIGxldCB1bml0ID0gJ2dDTzJlcS9rV2gnO1xuICAgICAgbGV0IHBvd2VyQ29uc3VtcHRpb24gPSBpbnB1dC5wb3dlcl9jb25zdW1wdGlvbjtcblxuICAgICAgaWYgKCFpbnB1dC5wb3dlcl9jb25zdW1wdGlvbikge1xuICAgICAgICBwb3dlckNvbnN1bXB0aW9uID0gMTtcbiAgICAgICAgdW5pdCA9ICdnQ08yZXEnO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFydCA9IGRheWpzKGlucHV0LnRpbWVzdGFtcCk7XG4gICAgICBjb25zdCBlbmQgPSBzdGFydC5hZGQoaW5wdXQuZHVyYXRpb24sICdzZWNvbmQnKTtcblxuICAgICAgY29uc3QgY2FyYm9uSW50ZW5zaXR5UGFyYW1zID0gaW5wdXQuem9uZVxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHpvbmU6IGlucHV0LnpvbmUsXG4gICAgICAgICAgICBzdGFydDogc3RhcnQudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgIGVuZDogZW5kLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgfVxuICAgICAgICA6IHtcbiAgICAgICAgICAgIGxvbjogaW5wdXQubG9uZ2l0dWRlLFxuICAgICAgICAgICAgbGF0OiBpbnB1dC5sYXRpdHVkZSxcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydC50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgZW5kOiBlbmQudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICB9O1xuXG4gICAgICBjb25zdCBjYXJib25JbnRlbnNpdGllcyA9IGFwaS5nZXRDYXJib25JbnRlbnNpdHkoY2FyYm9uSW50ZW5zaXR5UGFyYW1zKTtcblxuICAgICAgY29uc3QgbnVtSG91cnMgPSBNYXRoLmZsb29yKGlucHV0LmR1cmF0aW9uIC8gMzYwMCk7XG4gICAgICBjb25zdCBibG9ja3MgPSBbLi4uQXJyYXkobnVtSG91cnMpLmtleXMoKV07XG5cbiAgICAgIC8vIEZvciBlYWNoIGZ1bGwgaG91ciwgY2FsY3VsYXRlIHRoZSByYXRpbyBvZiB0aGUgaG91ciB0aGF0IGlzIGluIHRoZSBibG9ja1xuICAgICAgY29uc3QgaG91cmx5UmF0aW9zID0gYmxvY2tzLm1hcChob3VyID0+IHtcbiAgICAgICAgLy8gVGhpcyBpcyB0aGUgZmlyc3QgaG91cmx5IGJsb2NrLCB0aGUgcmF0aW8gaXMgdGhlIHRpbWUgYmV0d2VlbiB0aGUgc3RhcnQgYW5kIHRoZSBuZXh0IGhvdXIuXG4gICAgICAgIGlmIChob3VyID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHN0YXJ0LmFkZCgxLCAnaG91cicpLnN0YXJ0T2YoJ2hvdXInKS5kaWZmKHN0YXJ0LCAnc2Vjb25kJykgLyAzNjAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGlzIGlzIHRoZSBsYXN0IGhvdXJseSBibG9jaywgdGhlIHJhdGlvIGlzIHRoZSB0aW1lIGJldHdlZW4gdGhlIHN0YXJ0IG9mIHRoZSBob3VyIGFuZCB0aGUgZW5kLlxuICAgICAgICBpZiAoaG91ciA9PT0gbnVtSG91cnMgLSAxKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGVuZC5kaWZmKHN0YXJ0LmFkZChob3VyLCAnaG91cicpLnN0YXJ0T2YoJ2hvdXInKSwgJ3NlY29uZCcpIC8gMzYwMFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdG90YWxDYXJib25JbnRlbnNpdHkgPSBhd2FpdCBjYXJib25JbnRlbnNpdGllcy50aGVuKGludGVuc2l0aWVzID0+XG4gICAgICAgIGludGVuc2l0aWVzLnJlZHVjZSgobWVtbywgY2ksIGluZGV4KSA9PiB7XG4gICAgICAgICAgbWVtbyArPSBjaS52YWx1ZSAqIGhvdXJseVJhdGlvc1tpbmRleF07XG4gICAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgICAgIH0sIDApXG4gICAgICApO1xuXG4gICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgIC4uLmlucHV0LFxuICAgICAgICBjYXJib25JbnRlbnNpdHk6IHRvdGFsQ2FyYm9uSW50ZW5zaXR5ICogcG93ZXJDb25zdW1wdGlvbixcbiAgICAgICAgdW5pdDogdW5pdCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBtZXRhZGF0YSxcbiAgICBleGVjdXRlLFxuICB9O1xufTtcbiJdfQ==