198 lines
6.2 KiB
TypeScript
198 lines
6.2 KiB
TypeScript
import fs from 'fs';
|
|
import axios, { Axios, AxiosResponse } from "axios";
|
|
import { wrapper } from 'axios-cookiejar-support';
|
|
import { CookieJar } from 'tough-cookie';
|
|
import { FileCookieStore } from 'tough-cookie-file-store';
|
|
import { EnergyDTO, EnergyRequestDTO, Payload, PowerDTO, PowerRequestDTO, ReadingDTO, ReadingRequestDTO } from "./types";
|
|
import { TauronConfig } from '../config';
|
|
|
|
export * from './types';
|
|
|
|
const LOGIN_API = `https://logowanie.tauron-dystrybucja.pl/login`;
|
|
const BASE_URL = 'https://elicznik.tauron-dystrybucja.pl';
|
|
const ENERGY_API = '/energia/api';
|
|
const POWER_API = '/moc/api';
|
|
const READING_API = '/odczyty/api';
|
|
|
|
/**
|
|
* Utility class for Tauron API.
|
|
* @param config - configuration of service
|
|
*/
|
|
export const Tauron = class {
|
|
#http: Axios;
|
|
#config: TauronConfig;
|
|
|
|
constructor(config: TauronConfig) {
|
|
// TODO: It should be paths instead of raw credentials
|
|
this.#config = config;
|
|
|
|
this.#http = wrapper(axios.create({
|
|
baseURL: BASE_URL,
|
|
jar: new CookieJar(new FileCookieStore(config.cookiesJarPath || './cookies.json')),
|
|
headers: {
|
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/jxl,image/webp,image/png,image/svg+xml,*/*;q=0.8',
|
|
'Accept-Language': 'en-US,en;q=0.5',
|
|
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
|
'Sec-GPC': '1',
|
|
'Upgrade-Insecure-Requests': '1',
|
|
'Sec-Fetch-Dest': 'document',
|
|
'Sec-Fetch-Mode': 'navigate',
|
|
'Sec-Fetch-Site': 'none',
|
|
'Sec-Fetch-User': '?1',
|
|
'Priority': 'u=0, i',
|
|
},
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Performs the whole login process flow including:
|
|
* - directing to the main page
|
|
* - doing toe actual login
|
|
* - setting the measurement base point
|
|
*/
|
|
async #login() {
|
|
await this.#http.get(LOGIN_API);
|
|
|
|
await this.#http.postForm(LOGIN_API, {
|
|
username: fs.readFileSync(this.#config.usernamePath, 'utf8'),
|
|
password: fs.readFileSync(this.#config.passwordPath, 'utf8'),
|
|
service: BASE_URL
|
|
});
|
|
|
|
await this.#http.postForm('/ustaw_punkt', {
|
|
"site[client]": this.#config.point,
|
|
"page": "energy"
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generic function which performs the HTTP request.
|
|
* If the request fails, the login attempt will be performed and the function will be invoked again
|
|
* with new session cookies.
|
|
* @param callback - function which performs the request on Axios instance being passed as argument
|
|
* @returns response from callback function
|
|
*/
|
|
async query<T>(callback: (http: Axios) => Promise<AxiosResponse<T>>): Promise<AxiosResponse<T>> {
|
|
try {
|
|
return await callback(this.#http);
|
|
} catch(e) {
|
|
console.log("Session expired, login requested");
|
|
await this.#login();
|
|
return await callback(this.#http);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility function to handle Tauron API shape (success field) automatically.
|
|
* @param path - HTTP API path
|
|
* @param data - the HTTP payload
|
|
* @returns original response
|
|
*/
|
|
async #queryForm<T>(path: string, data: any): Promise<T> {
|
|
const response = await this.query(h => h.postForm<Payload<T>>(path, data));
|
|
|
|
if (!response.data.success) {
|
|
throw new Error(`Invalid data request (success == false): ${JSON.stringify(response.data)}`);
|
|
}
|
|
|
|
return response.data.data;
|
|
}
|
|
|
|
/**
|
|
* Returns the energy data for specific request payload.
|
|
* @param data - the payload supported by Tauron API
|
|
* @returns the energy data from Tauron API
|
|
*/
|
|
async getEnergy(data: EnergyRequestDTO): Promise<EnergyDTO> {
|
|
return this.#queryForm<EnergyDTO>(ENERGY_API, data);
|
|
}
|
|
|
|
/**
|
|
* Returns the energy data per specific day.
|
|
* @param day - measurement day
|
|
* @param type - type of measurement, can be 'consum' (regular one) or 'average'
|
|
* @returns the energy data from Tauron API
|
|
*/
|
|
async getEnergyForDay(day: string): Promise<EnergyDTO> {
|
|
return await this.getEnergy({
|
|
type: 'consum',
|
|
profile: "full time",
|
|
from: day,
|
|
to: day,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns the energy data per specific dates range.
|
|
* @param from - the measurement starting date
|
|
* @param to - the measurement ending date
|
|
* @param type - type of measurement, can be 'consum' (regular one) or 'average'
|
|
* @returns the energy data from Tauron API
|
|
*/
|
|
async getEnergyForRange(from: string, to: string): Promise<EnergyDTO> {
|
|
return await this.getEnergy({
|
|
type: 'consum',
|
|
from,
|
|
to,
|
|
profile: "range"
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns the energy data per specific year.
|
|
* @param year measurement year
|
|
* @param type - type of measurement, can be 'consum' (regular one) or 'average'
|
|
* @returns the energy data from Tauron API
|
|
*/
|
|
async getEnergyForYear(year: string): Promise<EnergyDTO> {
|
|
return await this.getEnergy({
|
|
type: 'consum',
|
|
profile: "year",
|
|
from: `01.01.${year}`,
|
|
to: `31.12.${year}`,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns the power data for specific request payload.
|
|
* @param data - the payload supported by Tauron API
|
|
* @returns the power data from Tauron API
|
|
*/
|
|
async getPower(data: PowerRequestDTO): Promise<PowerDTO[]> {
|
|
return this.#queryForm<PowerDTO[]>(POWER_API, data);
|
|
}
|
|
|
|
/**
|
|
* Returns the power data per specific dates range.
|
|
* @param from - the measurement starting date
|
|
* @param to - the measurement ending date
|
|
* @returns the power data from Tauron API
|
|
*/
|
|
async getPowerForRange(from: string, to: string): Promise<PowerDTO[]> {
|
|
return await this.getPower({ from, to });
|
|
}
|
|
|
|
/**
|
|
* Returns the reading data for specific request payload.
|
|
* @param data - the payload supported by Tauron API
|
|
* @returns the reading data from Tauron API
|
|
*/
|
|
async getReading(data: ReadingRequestDTO): Promise<ReadingDTO[]> {
|
|
return this.#queryForm<ReadingDTO[]>(READING_API, data);
|
|
}
|
|
|
|
/**
|
|
* Returns the readings per specific dates range.
|
|
* @param from - the measurement starting date
|
|
* @param to - the measurement ending date
|
|
* @returns the readings from Tauron API
|
|
*/
|
|
async getReadingForRange(from: string, to: string): Promise<ReadingDTO[]> {
|
|
return await this.getReading({
|
|
from,
|
|
to,
|
|
type: 'energia-pobrana',
|
|
});
|
|
}
|
|
};
|