[APP][Pro] Power by the Hour: Insights per hour, day, month and year

I want to use this app to do some things when power is cheapest, for example set the heating to high, charge my car, etc. To that end I’m looking for a card that fires once at the start of an unbroken period of n hours in which the average price is cheapest that day, and an event that fires at the end of that period.

Perhaps I’m misunderstanding something or doing something wrong, but it seems like the app does not provide those events.

I’ve tried using the “de gem. prijs komende x U wordt het laagst binnen y” and “de gem. prijs komende x U wordt het laagst in de y uren voor z uur” cards, but those fire every hour, instead of just once at the start of the period. And I can’t see a card at all that fires at the end of the period.

Which cards should I use so that I can start a flow once at the start of the cheapest period of n hours in the day, and start a flow once at the end of the same period? If that is not possible, would it be possible to add cards which provide that functionality?

Well Homey Energy is rubbish what come to 15 minutes prices. All cards are for hourly prices, so it’s useless if the goal is to use 15 minute prices.

works fine for me together with Logic

@Gruijter I think Stekker.app is also not working anymore.
Maybe the stopped their AI forecast due to ‘illegal’ use :slight_smile:

I am trying to create an automation for my dishwasher (Eco program takes about 3 hours), so that it will automatically start at the moment when the average price over the next 3 hours is the lowest within a period of the next 12 hours.​
I am currently using a virtual device/switch that I turn on manually. As soon as this is on, the program will only start if the price is low enough.​
Problem: I do not fully understand the first card, or maybe I am using the wrong one.​
Goal: Start Eco when the average price for 3 hours is the lowest in the coming 12 hours (not per hour, but average over a 3‑hour block).​
Can someone explain how I should fill in this card?​

No I meant the capabilities that PBTH has. Things like “hour is one of 3 cheapest hours”, but just in 15 minute intervals. You mentioned that anyone can use Homey Energy, but my point is that it doesn’t have any cards to build logic around 15 min prices. Sure, with Logic you can read the price now, but that’s it. PBTH is the only working solution that I know of, but it’s also not yet officially released.

I have the same problem. Does anyone know a fix ? Whenever I change anything in the device (even the pictogram / icon) I get the time out error.

The 10 second timeout issue is related to the my.homey.app web ui. This has been reported to Athom but for now there is no fix. If you try the mobile app to make those changes there shouldn’t be the same timeout.

I’m experiencing the same. I noticed it on New Year’s Day when I wanted to adjust the tax. I still haven’t managed to do it so far.

It is also in the mobile app.

Well, I don’t know what happened but after deleting and adding the NL DAP and letting it there for 8 hours, it suddenly works :man_shrugging:

v7.0.5 was just released as tetst: https://homey.app/a/com.gruijter.powerhour/test/

  • BAT fixed 15min pricing.
  • Extra charts cache.
  • Added flow card to set daily cost.
  • homey-api@3.15.0

Thx to Stef Kampen and Piznel for their code contributions!

Note that DAP pricing info is unreliable for now, because of ENTSO-E enforcing a rate limit on price fetching for Power by the Hour. I’m looking into a user friendly way to solve this.

4 Likes

Here’s what I found out about 15-min rates from Elering: Transmission System Operator (TSO) of Estonia.

I found it interesting that Elering is one of the few that get the rates from ENTSO-E (XML) and then make them available in JSON with their own API. It is publicly available without registration and with a fair use policy.

Calling the Elering Dashboard API every 15 minutes is well within the “fair use” threshold for public energy data.

The “Safe” Limits

While Elering does not publish a strict “requests-per-second” cap for its public dashboard, general industry standards for TSO (Transmission System Operator) APIs and specific HEMS (Home Energy Management System) guidelines recommend a polling frequency of once every 15 minutes.

  • Your Frequency: 1 request every 15 minutes = 96 requests per day.

  • The “Danger” Zone: Most public APIs only begin to throttle or flag IP addresses if they see aggressive polling (e.g., more than 1 request per minute, or 1,440+ requests per day).

So I have asked Gemini for a script that polls the Elering API every 15 minutes and it seems to work well.

The real source of course is ENTSO-E which is free but requires a one-time registration to get an API Key. I will add that once I receive it and will include a conversion from XML to JSON.

@Gruijter I would prefer to work with PBTH. Are you still considering to add an individual API key to the app? Note: it seems ENTSO-E have relaxed their API rate limit policy

// --- Estonia 15-Minute Electricity Price v1.3 (Elering)---
/**
 * Estonia 15-Minute Electricity Price Fetcher
 * Returns: JSON string { "0": price_in_eur, "1": price_in_eur, ... }
 * Coverage: 8 Hours (33 blocks total)
 */

const region = 'ee';
const forecastHours = 8;
const intervalsPerHour = 4;
const maxRetries = 3;
const retryDelayMs = 30000; // 30 seconds

const now = new Date();
const nowSeconds = Math.floor(now.getTime() / 1000);

// Set window from 15 mins ago to 9 hours ahead to ensure overlap
const start = new Date(now.getTime() - 900000).toISOString();
const end = new Date(now.getTime() + (forecastHours + 1) * 3600000).toISOString();
const url = `https://dashboard.elering.ee/api/nps/price?start=${start}&end=${end}`;

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function fetchPrices(attempt = 1) {
  try {
    const response = await fetch(url);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const json = await response.json();
    const prices = json.data[region];
    
    if (!prices || prices.length === 0) {
      throw new Error("Empty data received from Elering");
    }

    let priceObject = {};

    // Map intervals to indices: 0 (now) up to index 32 (8 hours)
    for (let i = 0; i <= (forecastHours * intervalsPerHour); i++) {
      const targetTime = nowSeconds + (i * 15 * 60);
      
      const priceBlock = prices.find(p => {
        const pStart = p.timestamp;
        const pEnd = p.timestamp + 900;
        return targetTime >= pStart && targetTime < pEnd;
      });

      if (priceBlock) {
        // Convert EUR/MWh to EUR/kWh (divide by 1000)
        priceObject[i] = parseFloat((priceBlock.price / 1000).toFixed(4));
      }
    }

    return JSON.stringify(priceObject);

  } catch (error) {
    if (attempt < maxRetries) {
      console.log(`Attempt ${attempt} failed: ${error.message}. Retrying in 30s...`);
      await delay(retryDelayMs);
      return await fetchPrices(attempt + 1);
    } else {
      // Return specific JSON error if final attempt fails
      return JSON.stringify({ 
        "error": "Failed to fetch data", 
        "details": error.message,
        "timestamp": now.toISOString()
      });
    }
  }
}

return await fetchPrices();

just extract pricing from Homey Energy.

Not available for Homey Pro 2019 and earlier though.

Here’s an idea: Why don’t you poll ENTSO-E once per hour as before. During the hour you can shift the 15-min prices for each 15 minutes.

Not sure how this would work in your app :smiling_face_with_three_hearts:

(I assume there is no chance that ENTSO-E will review the day ahead prices once they are public because once publicised, it is like a contract commitment)

I made a universal script that pulls the data from ENTSO-E directly (I obtained the API key within 24 hours from ENTSO-E). It works beautifully and it outputs a JSON with all 15-min or 30-min or 60-min prices for any country in Europe.

To get a price from it, just use the Homey built-in logic card Parse as JSON with path $[“0”] for index 0 (current price), etc. If anybody is interested, let me know.