class FrankEnergie { constructor(authToken = null, refreshToken = null) { this.DATA_URL = "https://frank-graphql-prod.graphcdn.app/"; this.auth = authToken || refreshToken ? { authToken, refreshToken } : null; } async query(queryData) { const headers = { 'Content-Type': 'application/json', ...(this.auth && { 'Authorization': `Bearer ${this.auth.authToken}` }) }; try { const response = await fetch(this.DATA_URL, { method: 'POST', headers, body: JSON.stringify(queryData) }); const data = await response.json(); if (data.errors) { for (const error of data.errors) { if (error.message === "user-error:auth-not-authorised") { throw new Error("Authentication required"); } } } return data; } catch (error) { throw new Error(`Request failed: ${error.message}`); } } async login(username, password) { const query = { query: ` mutation Login($email: String!, $password: String!) { login(email: $email, password: $password) { authToken refreshToken } } `, operationName: "Login", variables: { email: username, password } }; const response = await this.query(query); this.auth = response.data.login; return this.auth; } async getPrices(startDate, endDate) { const query = { query: ` query MarketPrices($startDate: Date!, $endDate: Date!) { marketPricesElectricity(startDate: $startDate, endDate: $endDate) { from till marketPrice marketPriceTax sourcingMarkupPrice energyTaxPrice } marketPricesGas(startDate: $startDate, endDate: $endDate) { from till marketPrice marketPriceTax sourcingMarkupPrice energyTaxPrice } } `, variables: { startDate: startDate.toISOString().split('T')[0], endDate: endDate.toISOString().split('T')[0] }, operationName: "MarketPrices" }; return await this.query(query); } async getSmartBatteries() { if (!this.auth) { throw new Error("Authentication required"); } const query = { query: ` query SmartBatteries { smartBatteries { brand capacity createdAt externalReference id maxChargePower maxDischargePower provider updatedAt } } `, operationName: "SmartBatteries" }; return await this.query(query); } async getSmartBatterySessions(deviceId, startDate, endDate) { if (!this.auth) { throw new Error("Authentication required"); } const query = { query: ` query SmartBatterySessions($startDate: String!, $endDate: String!, $deviceId: String!) { smartBatterySessions( startDate: $startDate endDate: $endDate deviceId: $deviceId ) { deviceId periodEndDate periodStartDate periodTradingResult sessions { cumulativeTradingResult date tradingResult } totalTradingResult } } `, operationName: "SmartBatterySessions", variables: { deviceId, startDate: startDate.toISOString().split('T')[0], endDate: endDate.toISOString().split('T')[0] } }; return await this.query(query); } isAuthenticated() { return this.auth !== null; } } class OnbalansMarkt { constructor(apiKey) { this.apiUrl = 'https://onbalansmarkt.com/nexus/api/live'; this.apiKey = apiKey; } async sendMeasurement({ timestamp, batteryResult, batteryResultTotal = null, batteryCharge = null, batteryPower = null, deliveryToday = null, productionToday = null, loadBalancingActive = null, solarResult = null, chargerResult = null }) { // Validate required fields if (!timestamp || !batteryResult) { throw new Error('timestamp and batteryResult are required fields'); } // Prepare the payload const payload = { timestamp, batteryResult: batteryResult.toString(), ...(batteryResultTotal !== null && { batteryResultTotal: batteryResultTotal.toString() }), ...(batteryCharge !== null && { batteryCharge: batteryCharge.toString() }), ...(batteryPower !== null && { batteryPower: batteryPower.toString() }), ...(deliveryToday !== null && { deliveryToday: deliveryToday.toString() }), ...(productionToday !== null && { productionToday: productionToday.toString() }), ...(loadBalancingActive !== null && { loadBalancingActive: loadBalancingActive.toString() }), ...(solarResult !== null && { solarResult: solarResult.toString() }), ...(chargerResult !== null && { chargerResult: chargerResult.toString() }) }; try { const response = await fetch(this.apiUrl, { method: 'POST', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error sending measurement:', error); throw error; } } } const frank = new FrankEnergie(); await frank.login("mijnfrankusername@gmail.com", "mijnfrankpassword"); const onbalansmarkt = new OnbalansMarkt("API-KEY-ONBALANSMARKT.COM"); // Get all smart batteries const batteries = await frank.getSmartBatteries(); console.log(batteries); let yesterday = new Date(); yesterday.setHours(0,0,0,0); yesterday.setDate(yesterday.getDate() - 1); // Get sessions for a specific battery if (batteries.data.smartBatteries.length > 0) { const batteryId = batteries.data.smartBatteries[0].id; const sessions = await frank.getSmartBatterySessions( batteryId, yesterday, yesterday ); console.log(sessions); onbalansmarkt.sendMeasurement({ timestamp: yesterday.toISOString(), batteryResult: sessions.data.smartBatterySessions.periodTradingResult, loadBalancingActive: "off" }); }