@powercalc/power-router 1.0.25 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +11 -16
- package/dist/converter.js +7 -11
- package/dist/genTypes.js +10 -14
- package/dist/index.js +2 -5
- package/dist/load.js +1 -5
- package/dist/router/controllers/LoadAndParse.js +10 -14
- package/dist/router/controllers/Router.js +19 -23
- package/dist/router/index.js +1 -5
- package/dist/router/interfaces/config.js +1 -2
- package/dist/router/interfaces/entsoe.js +1 -2
- package/dist/router/interfaces/queryoptions.js +4 -7
- package/dist/router/interfaces/types.js +1 -2
- package/dist/router/services/CommonTimestamps.js +8 -12
- package/dist/router/services/Eurostat.js +5 -9
- package/dist/router/services/LoadService.js +19 -23
- package/dist/router/services/Loader.js +16 -20
- package/dist/router/services/ParseEdifact.js +5 -9
- package/dist/router/services/ParseInstalled.js +1 -5
- package/dist/router/services/batch/maxHydrofill.js +9 -13
- package/package.json +1 -2
package/dist/app.js
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
require("reflect-metadata");
|
|
1
|
+
import 'reflect-metadata';
|
|
7
2
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = '0';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const app = (
|
|
3
|
+
import express from 'express';
|
|
4
|
+
import cors from 'cors';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { cwd } from 'process';
|
|
7
|
+
import { PowerRouter } from './router/controllers/Router';
|
|
8
|
+
const app = express();
|
|
14
9
|
const port = 30000;
|
|
15
10
|
const config = {
|
|
16
11
|
securityToken: '1c608639-afff-4d73-bfe1-a960fe7ea8da',
|
|
17
|
-
cacheDir:
|
|
12
|
+
cacheDir: join(cwd(), 'data'),
|
|
18
13
|
entsoeDomain: "https://web-api.tp.entsoe.eu"
|
|
19
14
|
};
|
|
20
|
-
app.use((
|
|
21
|
-
app.use('/entsoe',
|
|
22
|
-
app.use('/public',
|
|
15
|
+
app.use(cors());
|
|
16
|
+
app.use('/entsoe', PowerRouter.init(config));
|
|
17
|
+
app.use('/public', express.static('public'));
|
|
23
18
|
// app.use('/config', express.static('dist/config', { maxAge: 100000 }));
|
|
24
19
|
app.listen(port, () => {
|
|
25
20
|
console.log(`Server listening on port ${port}`);
|
package/dist/converter.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,21 +7,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const promises_1 = require("node:fs/promises");
|
|
16
|
-
class Convert {
|
|
10
|
+
import { GenTypes } from "./genTypes";
|
|
11
|
+
import { Hydrofill } from "./router/services/batch/maxHydrofill";
|
|
12
|
+
import { writeFile } from 'node:fs/promises';
|
|
13
|
+
export class Convert {
|
|
17
14
|
static start() {
|
|
18
15
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
16
|
const countries = yield this.getCountries();
|
|
20
17
|
console.log(countries);
|
|
21
18
|
for (const country of countries) {
|
|
22
|
-
const types = yield
|
|
19
|
+
const types = yield GenTypes.getTypes(country.code);
|
|
23
20
|
country.types = types;
|
|
24
21
|
console.log(country.name, types.join(', '));
|
|
25
|
-
const h = yield
|
|
22
|
+
const h = yield Hydrofill.getMaxHydrofill(country.code);
|
|
26
23
|
if (h.max) {
|
|
27
24
|
const GW = Math.round(h.max / 1000) + ' GW';
|
|
28
25
|
console.log(country.name, GW);
|
|
@@ -37,7 +34,7 @@ class Convert {
|
|
|
37
34
|
const hydrofill = yield this.getHydrofill(country.code);
|
|
38
35
|
}
|
|
39
36
|
console.log(countries);
|
|
40
|
-
|
|
37
|
+
writeFile('data/countrydata.json', JSON.stringify(countries, null, 2), 'utf-8');
|
|
41
38
|
});
|
|
42
39
|
}
|
|
43
40
|
static getCountries() {
|
|
@@ -76,5 +73,4 @@ class Convert {
|
|
|
76
73
|
});
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
|
-
exports.Convert = Convert;
|
|
80
76
|
Convert.start();
|
package/dist/genTypes.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,12 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const promises_1 = require("node:fs/promises");
|
|
16
|
-
class GenTypes {
|
|
10
|
+
import { gzip } from "node:zlib";
|
|
11
|
+
import { Load } from "./load";
|
|
12
|
+
import { writeFile } from 'node:fs/promises';
|
|
13
|
+
export class GenTypes {
|
|
17
14
|
static getTypes(country) {
|
|
18
15
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
16
|
let types = [];
|
|
@@ -23,20 +20,20 @@ class GenTypes {
|
|
|
23
20
|
let max;
|
|
24
21
|
for (let year = minYear; year <= maxYear; year++) {
|
|
25
22
|
for (let month = 1; month <= 12; month++) {
|
|
26
|
-
const gen = yield
|
|
27
|
-
const price = yield
|
|
28
|
-
const load = yield
|
|
23
|
+
const gen = yield Load.getGeneration(country, year, month);
|
|
24
|
+
const price = yield Load.getPrice(country, year, month);
|
|
25
|
+
const load = yield Load.getLoad(country, year, month);
|
|
29
26
|
const all = this.makeGen(gen, load, price);
|
|
30
27
|
const gzipfilename = `data/gzip/${country}-${year}-${month}.json.gzip`;
|
|
31
28
|
const filename = `data/generation/${country}-${year}-${month}.json`;
|
|
32
29
|
const buf = Buffer.from(JSON.stringify(all), 'utf-8');
|
|
33
|
-
|
|
30
|
+
gzip(buf, (_, result) => __awaiter(this, void 0, void 0, function* () {
|
|
34
31
|
var _a;
|
|
35
|
-
yield
|
|
32
|
+
yield writeFile(gzipfilename, result, 'utf-8');
|
|
36
33
|
// console.log(gen.dataset.map((item:any) => item.label))
|
|
37
34
|
types = types.concat(((_a = gen.dataset) === null || _a === void 0 ? void 0 : _a.map((item) => item.psrType)) || []);
|
|
38
35
|
}));
|
|
39
|
-
yield
|
|
36
|
+
yield writeFile(filename, JSON.stringify(all, null, 2), 'utf-8');
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
return [...new Set(types)].sort();
|
|
@@ -61,4 +58,3 @@ class GenTypes {
|
|
|
61
58
|
return all;
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
|
-
exports.GenTypes = GenTypes;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.PowerRouter = void 0;
|
|
4
|
-
const Router_1 = require("./router/controllers/Router");
|
|
5
|
-
Object.defineProperty(exports, "PowerRouter", { enumerable: true, get: function () { return Router_1.PowerRouter; } });
|
|
1
|
+
import { PowerRouter } from './router/controllers/Router';
|
|
2
|
+
export { PowerRouter };
|
package/dist/load.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,9 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
exports.Load = void 0;
|
|
13
|
-
class Load {
|
|
10
|
+
export class Load {
|
|
14
11
|
static getCountries() {
|
|
15
12
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
13
|
const url = 'https://powercalculator.eu/entsoe/datalists/countries';
|
|
@@ -47,4 +44,3 @@ class Load {
|
|
|
47
44
|
});
|
|
48
45
|
}
|
|
49
46
|
}
|
|
50
|
-
exports.Load = Load;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,18 +7,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const queryoptions_1 = require("../interfaces/queryoptions");
|
|
17
|
-
class LoadAndParse {
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { readFileSync } from 'fs';
|
|
12
|
+
import { LoadService } from '../services/LoadService';
|
|
13
|
+
import { Format, PosNeg } from '../interfaces/queryoptions';
|
|
14
|
+
export class LoadAndParse {
|
|
18
15
|
constructor(config) {
|
|
19
16
|
this.country = '';
|
|
20
|
-
const countriesFile =
|
|
21
|
-
this.countries = JSON.parse(
|
|
22
|
-
this.loadService = new
|
|
17
|
+
const countriesFile = join(__dirname, '../config/countries.json'); // Set the path to your config file
|
|
18
|
+
this.countries = JSON.parse(readFileSync(countriesFile, 'utf8')); // Read the config file from disk
|
|
19
|
+
this.loadService = new LoadService(config);
|
|
23
20
|
}
|
|
24
21
|
get(req, chartType) {
|
|
25
22
|
var _a;
|
|
@@ -32,10 +29,10 @@ class LoadAndParse {
|
|
|
32
29
|
const queryOptions = {};
|
|
33
30
|
const year = parseInt(req.params.year);
|
|
34
31
|
const month = parseInt(req.params.month);
|
|
35
|
-
if (req.query.posneg ===
|
|
32
|
+
if (req.query.posneg === PosNeg.POS || req.query.posneg === PosNeg.NEG) {
|
|
36
33
|
queryOptions.posneg = req.query.posneg;
|
|
37
34
|
}
|
|
38
|
-
if (typeof (req.query.format) === 'string' && Object.values(
|
|
35
|
+
if (typeof (req.query.format) === 'string' && Object.values(Format).includes(req.query.format)) {
|
|
39
36
|
queryOptions.format = req.query.format;
|
|
40
37
|
}
|
|
41
38
|
let reload = false;
|
|
@@ -65,4 +62,3 @@ class LoadAndParse {
|
|
|
65
62
|
});
|
|
66
63
|
}
|
|
67
64
|
}
|
|
68
|
-
exports.LoadAndParse = LoadAndParse;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,20 +7,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const path_1 = require("path");
|
|
21
|
-
class PowerRouter {
|
|
10
|
+
import { Router } from 'express';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { stat, writeFile } from 'fs/promises';
|
|
13
|
+
import { gzipSync } from 'zlib';
|
|
14
|
+
import { Buffer } from 'node:buffer';
|
|
15
|
+
import { createReadStream } from 'fs';
|
|
16
|
+
import { LoadAndParse } from './LoadAndParse';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
export class PowerRouter {
|
|
22
19
|
static init(config) {
|
|
23
20
|
console.log('init', config);
|
|
24
|
-
const router =
|
|
21
|
+
const router = Router();
|
|
25
22
|
router.get(`/:country/:year/:month`, (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
26
23
|
yield this.load(config, req, res, 'power');
|
|
27
24
|
}));
|
|
@@ -38,12 +35,12 @@ class PowerRouter {
|
|
|
38
35
|
yield this.load(config, req, res, 'countrydata');
|
|
39
36
|
}));
|
|
40
37
|
router.get('/types', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
41
|
-
const filePath =
|
|
38
|
+
const filePath = join(__dirname, '..', 'config', 'types.json');
|
|
42
39
|
res.set({ 'Cache-Control': 'max-age=86400' });
|
|
43
40
|
res.sendFile(filePath);
|
|
44
41
|
}));
|
|
45
42
|
router.get('/countries', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
46
|
-
const filePath =
|
|
43
|
+
const filePath = join(__dirname, '..', 'config', 'countrydata.json');
|
|
47
44
|
res.set({ 'Cache-Control': 'max-age=86400' });
|
|
48
45
|
res.sendFile(filePath);
|
|
49
46
|
}));
|
|
@@ -51,7 +48,7 @@ class PowerRouter {
|
|
|
51
48
|
}
|
|
52
49
|
static load(config, req, res, type) {
|
|
53
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
-
const entsoeLoader = new
|
|
51
|
+
const entsoeLoader = new LoadAndParse(config);
|
|
55
52
|
const cacheTime = this.calcCacheTime(req);
|
|
56
53
|
const successHeaders = {
|
|
57
54
|
'Cache-Control': `public, max-age=${cacheTime}`,
|
|
@@ -61,11 +58,11 @@ class PowerRouter {
|
|
|
61
58
|
try {
|
|
62
59
|
let cacheData;
|
|
63
60
|
const cacheKey = req.url;
|
|
64
|
-
const cacheFilePath = `${config.cacheDir}/${
|
|
61
|
+
const cacheFilePath = `${config.cacheDir}/${createHash('md5').update(cacheKey).digest('hex')}.json.gz`;
|
|
65
62
|
if (!(req.headers['reload'] === 'full')) {
|
|
66
63
|
// check if there is a cache file for this request
|
|
67
64
|
try {
|
|
68
|
-
const stats = yield
|
|
65
|
+
const stats = yield stat(cacheFilePath);
|
|
69
66
|
const modtime = stats.mtime.getTime();
|
|
70
67
|
// Check if the If-Modified-Since header matches the last modified date
|
|
71
68
|
const ifModifiedSince = req.headers['if-modified-since'];
|
|
@@ -76,7 +73,7 @@ class PowerRouter {
|
|
|
76
73
|
res.setHeader('Last-Modified', (new Date(modtime)).toUTCString());
|
|
77
74
|
res.set(successHeaders);
|
|
78
75
|
console.log('cached');
|
|
79
|
-
|
|
76
|
+
createReadStream(cacheFilePath)
|
|
80
77
|
.pipe(res);
|
|
81
78
|
return;
|
|
82
79
|
}
|
|
@@ -88,9 +85,9 @@ class PowerRouter {
|
|
|
88
85
|
if (!cacheData) {
|
|
89
86
|
// LOAD THE DATA FROM SOURCE
|
|
90
87
|
const body = yield entsoeLoader.get(req, type);
|
|
91
|
-
const buf =
|
|
92
|
-
const cacheDataBuffer =
|
|
93
|
-
yield
|
|
88
|
+
const buf = Buffer.from(JSON.stringify(body), 'utf-8');
|
|
89
|
+
const cacheDataBuffer = gzipSync(buf);
|
|
90
|
+
yield writeFile(cacheFilePath, cacheDataBuffer, 'utf-8');
|
|
94
91
|
res.setHeader('Last-Modified', (new Date()).toUTCString());
|
|
95
92
|
res.set(successHeaders);
|
|
96
93
|
res.send(cacheDataBuffer);
|
|
@@ -113,4 +110,3 @@ class PowerRouter {
|
|
|
113
110
|
}
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
|
-
exports.PowerRouter = PowerRouter;
|
package/dist/router/index.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PowerRouter = void 0;
|
|
4
|
-
var Router_1 = require("./controllers/Router");
|
|
5
|
-
Object.defineProperty(exports, "PowerRouter", { enumerable: true, get: function () { return Router_1.PowerRouter; } });
|
|
1
|
+
export { PowerRouter } from './controllers/Router';
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PosNeg = exports.Format = void 0;
|
|
4
|
-
var Format;
|
|
1
|
+
export var Format;
|
|
5
2
|
(function (Format) {
|
|
6
3
|
Format["EDIFACT"] = "edifact";
|
|
7
4
|
Format["EDIJSON"] = "edijson";
|
|
8
5
|
Format["SOURCES"] = "sources";
|
|
9
6
|
Format["KEYVALUE"] = "keyvalue";
|
|
10
|
-
})(Format
|
|
11
|
-
var PosNeg;
|
|
7
|
+
})(Format || (Format = {}));
|
|
8
|
+
export var PosNeg;
|
|
12
9
|
(function (PosNeg) {
|
|
13
10
|
PosNeg["POS"] = "pos";
|
|
14
11
|
PosNeg["NEG"] = "neg";
|
|
15
|
-
})(PosNeg
|
|
12
|
+
})(PosNeg || (PosNeg = {}));
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.CommonTimestamps = void 0;
|
|
4
|
-
const luxon_1 = require("luxon");
|
|
5
|
-
class CommonTimestamps {
|
|
1
|
+
import { DateTime, Duration } from "luxon";
|
|
2
|
+
export class CommonTimestamps {
|
|
6
3
|
static transform(all, startMonth, endMonth) {
|
|
7
4
|
const best = this.bestResolution(all);
|
|
8
5
|
const time = this.makeTimeArray(startMonth, endMonth, best);
|
|
@@ -58,7 +55,7 @@ class CommonTimestamps {
|
|
|
58
55
|
}
|
|
59
56
|
static interpolate(all, newTimes) {
|
|
60
57
|
const best = this.best(all);
|
|
61
|
-
const dur =
|
|
58
|
+
const dur = Duration.fromISO(best).as('milliseconds');
|
|
62
59
|
const data = all[best];
|
|
63
60
|
const sourceTimes = data.map(item => item.time);
|
|
64
61
|
/*
|
|
@@ -120,9 +117,9 @@ class CommonTimestamps {
|
|
|
120
117
|
return result;
|
|
121
118
|
}
|
|
122
119
|
static makeTimeArray(startIsoString, endIsoString, resolution) {
|
|
123
|
-
const duration =
|
|
124
|
-
const localStartTime =
|
|
125
|
-
const localEndTime =
|
|
120
|
+
const duration = Duration.fromISO(resolution).toMillis();
|
|
121
|
+
const localStartTime = DateTime.fromISO(startIsoString);
|
|
122
|
+
const localEndTime = DateTime.fromISO(endIsoString);
|
|
126
123
|
// Convert start and end time to UTC time using Luxon
|
|
127
124
|
const utcStartTime = localStartTime.toUTC();
|
|
128
125
|
const utcEndTime = localEndTime.toUTC();
|
|
@@ -147,7 +144,7 @@ class CommonTimestamps {
|
|
|
147
144
|
let minPeriod = '';
|
|
148
145
|
const keys = Object.keys(all);
|
|
149
146
|
keys.forEach(period => {
|
|
150
|
-
const dur =
|
|
147
|
+
const dur = Duration.fromISO(period);
|
|
151
148
|
if (dur.as('minutes') < min) {
|
|
152
149
|
min = dur.as('minutes');
|
|
153
150
|
minPeriod = period;
|
|
@@ -160,7 +157,7 @@ class CommonTimestamps {
|
|
|
160
157
|
let minPeriod = '';
|
|
161
158
|
Object.keys(all).forEach((key) => {
|
|
162
159
|
Object.keys(all[key]).forEach(period => {
|
|
163
|
-
const dur =
|
|
160
|
+
const dur = Duration.fromISO(period);
|
|
164
161
|
if (dur.as('minutes') < min) {
|
|
165
162
|
min = dur.as('minutes');
|
|
166
163
|
minPeriod = period;
|
|
@@ -170,4 +167,3 @@ class CommonTimestamps {
|
|
|
170
167
|
return minPeriod;
|
|
171
168
|
}
|
|
172
169
|
}
|
|
173
|
-
exports.CommonTimestamps = CommonTimestamps;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,12 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const fs_1 = require("fs");
|
|
14
|
-
const path_1 = require("path");
|
|
10
|
+
import { readFileSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
15
12
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = '0';
|
|
16
|
-
class EurostatAPI {
|
|
13
|
+
export class EurostatAPI {
|
|
17
14
|
constructor() {
|
|
18
15
|
this.countries = [];
|
|
19
16
|
this.fuels = {
|
|
@@ -28,8 +25,8 @@ class EurostatAPI {
|
|
|
28
25
|
['TJ_GCV', Math.pow(10, 12)],
|
|
29
26
|
['THS_T', 41868000000000], // joules per thousand metric tons of oil equivalent
|
|
30
27
|
]);
|
|
31
|
-
const countryPath =
|
|
32
|
-
const countriesString =
|
|
28
|
+
const countryPath = join(__dirname, '..', 'config/countries.json');
|
|
29
|
+
const countriesString = readFileSync(countryPath, 'utf-8');
|
|
33
30
|
this.countries = JSON.parse(countriesString);
|
|
34
31
|
}
|
|
35
32
|
convertToMWh(value, unit) {
|
|
@@ -82,4 +79,3 @@ class EurostatAPI {
|
|
|
82
79
|
});
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
|
-
exports.EurostatAPI = EurostatAPI;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,43 +7,41 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const queryoptions_1 = require("../interfaces/queryoptions");
|
|
21
|
-
class LoadService {
|
|
10
|
+
import { readFileSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { EntsoeLoader } from "./Loader";
|
|
13
|
+
import { EdifactParser } from "./ParseEdifact";
|
|
14
|
+
import { ParseInstalled } from "./ParseInstalled";
|
|
15
|
+
import { CommonTimestamps } from "./CommonTimestamps";
|
|
16
|
+
import { EurostatAPI } from "./Eurostat";
|
|
17
|
+
import { Format } from "../interfaces/queryoptions";
|
|
18
|
+
export class LoadService {
|
|
22
19
|
constructor(loaderConfig) {
|
|
23
20
|
this.loaderConfig = loaderConfig;
|
|
24
21
|
this.country = '';
|
|
25
|
-
const typesPath =
|
|
26
|
-
const types = JSON.parse(
|
|
27
|
-
this.loader = new
|
|
28
|
-
this.parser = new
|
|
29
|
-
this.parseInstalled = new
|
|
22
|
+
const typesPath = join(__dirname, '../config/types.json'); // Set the path to your config file
|
|
23
|
+
const types = JSON.parse(readFileSync(typesPath, 'utf8')); // Read the config file from disk
|
|
24
|
+
this.loader = new EntsoeLoader(loaderConfig);
|
|
25
|
+
this.parser = new EdifactParser(types);
|
|
26
|
+
this.parseInstalled = new ParseInstalled(types);
|
|
30
27
|
}
|
|
31
28
|
getPower(countryCode, year, month, queryOptions) {
|
|
32
29
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
30
|
const wanted = ['generation', 'price', 'consumption'];
|
|
34
|
-
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) ===
|
|
31
|
+
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) === Format.SOURCES) {
|
|
35
32
|
return this.loader.makeUrls(wanted, countryCode, year, month);
|
|
36
33
|
}
|
|
37
34
|
const edifactAsJson = yield this.loader.load(wanted, countryCode, year, month, queryOptions);
|
|
38
|
-
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) ===
|
|
35
|
+
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) === Format.EDIJSON) {
|
|
39
36
|
return edifactAsJson;
|
|
40
37
|
}
|
|
41
38
|
const parsed = yield this.parser.parseAll(edifactAsJson);
|
|
42
|
-
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) ===
|
|
39
|
+
if ((queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.format) === Format.KEYVALUE) {
|
|
43
40
|
return parsed;
|
|
44
41
|
}
|
|
45
42
|
const startMonth = (new Date(Date.UTC(year, month - 1))).toISOString();
|
|
46
43
|
const endMonth = (new Date(Date.UTC(year, month))).toISOString();
|
|
47
|
-
const ready =
|
|
44
|
+
const ready = CommonTimestamps.transform(parsed, startMonth, endMonth);
|
|
48
45
|
return ready;
|
|
49
46
|
});
|
|
50
47
|
}
|
|
@@ -83,7 +80,7 @@ class LoadService {
|
|
|
83
80
|
}
|
|
84
81
|
getFossil(country) {
|
|
85
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
-
const eurostat = new
|
|
83
|
+
const eurostat = new EurostatAPI();
|
|
87
84
|
return yield eurostat.load(country);
|
|
88
85
|
});
|
|
89
86
|
}
|
|
@@ -98,4 +95,3 @@ class LoadService {
|
|
|
98
95
|
});
|
|
99
96
|
}
|
|
100
97
|
}
|
|
101
|
-
exports.LoadService = LoadService;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,13 +7,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const date_fns_1 = require("date-fns");
|
|
17
|
-
class EntsoeLoader {
|
|
10
|
+
import { parseStringPromise } from 'xml2js';
|
|
11
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { add, format, sub } from 'date-fns';
|
|
14
|
+
export class EntsoeLoader {
|
|
18
15
|
constructor(loaderConfig) {
|
|
19
16
|
this.loaderConfig = loaderConfig;
|
|
20
17
|
this.config = loaderConfig;
|
|
@@ -34,14 +31,14 @@ class EntsoeLoader {
|
|
|
34
31
|
}
|
|
35
32
|
makeUrls(wanted, countryCode, year, month) {
|
|
36
33
|
let start = new Date(Date.UTC(year, month - 1));
|
|
37
|
-
start =
|
|
34
|
+
start = sub(start, { hours: 3 });
|
|
38
35
|
let end = new Date(Date.UTC(year, month));
|
|
39
|
-
end =
|
|
40
|
-
const periodStart =
|
|
41
|
-
const periodEnd =
|
|
42
|
-
const hydroStart =
|
|
43
|
-
const hydroPeriodStart =
|
|
44
|
-
const hydroPeriodEnd =
|
|
36
|
+
end = add(end, { hours: 3 });
|
|
37
|
+
const periodStart = format(start, 'yyyyMMddHHmm');
|
|
38
|
+
const periodEnd = format(end, 'yyyyMMddHHmm');
|
|
39
|
+
const hydroStart = sub(start, { days: 7 });
|
|
40
|
+
const hydroPeriodStart = format(hydroStart, 'yyyyMMddHHmm');
|
|
41
|
+
const hydroPeriodEnd = format(add(hydroStart, { days: 380 }), 'yyyyMMddHHmm');
|
|
45
42
|
let priceCountryCode = countryCode;
|
|
46
43
|
//germany luxemburg
|
|
47
44
|
if (countryCode === '10Y1001A1001A83F' || countryCode === '10YLU-CEGEDEL-NQ') {
|
|
@@ -104,13 +101,13 @@ class EntsoeLoader {
|
|
|
104
101
|
const simpleUrl = url.replace(/[\W_]+/g, "_");
|
|
105
102
|
let filename;
|
|
106
103
|
if (this.config.cacheDir) {
|
|
107
|
-
filename =
|
|
104
|
+
filename = join(this.config.cacheDir, simpleUrl + '.json');
|
|
108
105
|
}
|
|
109
106
|
try {
|
|
110
107
|
if (reload || !filename) {
|
|
111
108
|
throw Error('go for full reload');
|
|
112
109
|
}
|
|
113
|
-
const jsonString = yield
|
|
110
|
+
const jsonString = yield readFile(filename, 'utf-8');
|
|
114
111
|
return JSON.parse(jsonString);
|
|
115
112
|
}
|
|
116
113
|
catch (e) {
|
|
@@ -120,9 +117,9 @@ class EntsoeLoader {
|
|
|
120
117
|
return Promise.reject(new Error(`${response.status} ${response.statusText}`));
|
|
121
118
|
}
|
|
122
119
|
const data = yield response.text();
|
|
123
|
-
const json = yield
|
|
120
|
+
const json = yield parseStringPromise(data);
|
|
124
121
|
if (filename) {
|
|
125
|
-
|
|
122
|
+
writeFile(filename, JSON.stringify(json), 'utf-8');
|
|
126
123
|
}
|
|
127
124
|
return json;
|
|
128
125
|
}
|
|
@@ -135,4 +132,3 @@ class EntsoeLoader {
|
|
|
135
132
|
}, {});
|
|
136
133
|
}
|
|
137
134
|
}
|
|
138
|
-
exports.EntsoeLoader = EntsoeLoader;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.EdifactParser = void 0;
|
|
4
|
-
const luxon_1 = require("luxon");
|
|
5
|
-
class EdifactParser {
|
|
1
|
+
import { DateTime, Duration } from "luxon";
|
|
2
|
+
export class EdifactParser {
|
|
6
3
|
constructor(types) {
|
|
7
4
|
this.types = types;
|
|
8
5
|
this.psrName = {};
|
|
@@ -84,9 +81,9 @@ class EdifactParser {
|
|
|
84
81
|
return [startEndResolution.resolution, result];
|
|
85
82
|
}
|
|
86
83
|
makeTimeArray(startIsoString, endIsoString, resolution, timeSerie) {
|
|
87
|
-
const duration =
|
|
88
|
-
const localStartTime =
|
|
89
|
-
const localEndTime =
|
|
84
|
+
const duration = Duration.fromISO(resolution).toMillis();
|
|
85
|
+
const localStartTime = DateTime.fromISO(startIsoString);
|
|
86
|
+
const localEndTime = DateTime.fromISO(endIsoString);
|
|
90
87
|
// Convert start and end time to UTC time using Luxon
|
|
91
88
|
const utcStartTime = localStartTime.toUTC();
|
|
92
89
|
const utcEndTime = localEndTime.toUTC();
|
|
@@ -156,4 +153,3 @@ class EdifactParser {
|
|
|
156
153
|
return result;
|
|
157
154
|
}
|
|
158
155
|
}
|
|
159
|
-
exports.EdifactParser = EdifactParser;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ParseInstalled = void 0;
|
|
4
|
-
class ParseInstalled {
|
|
1
|
+
export class ParseInstalled {
|
|
5
2
|
constructor(types) {
|
|
6
3
|
this.types = types;
|
|
7
4
|
this.psrName = {};
|
|
@@ -42,4 +39,3 @@ class ParseInstalled {
|
|
|
42
39
|
return (_a = timeSeries === null || timeSeries === void 0 ? void 0 : timeSeries.MktPSRType) === null || _a === void 0 ? void 0 : _a[0].psrType;
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
|
-
exports.ParseInstalled = ParseInstalled;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,14 +7,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const path_1 = require("path");
|
|
15
|
-
const process_1 = require("process");
|
|
10
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { cwd } from "process";
|
|
16
13
|
//import { EntsoeLoader } from "../Loader";
|
|
17
14
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = '0';
|
|
18
|
-
class Hydrofill {
|
|
15
|
+
export class Hydrofill {
|
|
19
16
|
static start() {
|
|
20
17
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
18
|
const countries = yield this.getCountries();
|
|
@@ -30,10 +27,10 @@ class Hydrofill {
|
|
|
30
27
|
};
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
|
-
const countryFile =
|
|
30
|
+
const countryFile = join(__dirname, '../../config', 'countrydata.json');
|
|
34
31
|
console.log(countryFile);
|
|
35
|
-
const countryDataFile =
|
|
36
|
-
|
|
32
|
+
const countryDataFile = join(cwd(), 'data/countrydata.json');
|
|
33
|
+
writeFileSync(countryFile, JSON.stringify(countries, null, 2));
|
|
37
34
|
});
|
|
38
35
|
}
|
|
39
36
|
static getMaxHydrofill(country) {
|
|
@@ -67,8 +64,8 @@ class Hydrofill {
|
|
|
67
64
|
}
|
|
68
65
|
static getCountries() {
|
|
69
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
-
const configFile =
|
|
71
|
-
const countriesString =
|
|
67
|
+
const configFile = join(__dirname, '../../config', 'countries.json');
|
|
68
|
+
const countriesString = readFileSync(configFile, 'utf-8');
|
|
72
69
|
return JSON.parse(countriesString);
|
|
73
70
|
/*
|
|
74
71
|
const url = 'https://powercalculator.eu/entsoe/datalists/countries';
|
|
@@ -78,5 +75,4 @@ class Hydrofill {
|
|
|
78
75
|
});
|
|
79
76
|
}
|
|
80
77
|
}
|
|
81
|
-
exports.Hydrofill = Hydrofill;
|
|
82
78
|
Hydrofill.start();
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powercalc/power-router",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"type": "module",
|
|
8
7
|
"scripts": {
|
|
9
8
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
9
|
"v": "node -v",
|