Skip to content

Daily energy summary

At 23:55, reads today’s energy use, stores it for a week, and sends a notification with today’s value and the seven-day total.

You need a sensor with today’s energy in kWh (from the Energy dashboard, a utility meter, or your inverter), and persistence, which projects from the skeleton have.

apps/DailyEnergy.php
<?php
declare(strict_types=1);
namespace App;
use Stewart\Contracts\App;
use Stewart\Contracts\Automation;
use Stewart\Contracts\HaContext;
use Stewart\Contracts\Schedule\Scheduler;
use Stewart\Contracts\Store\Store;
use Stewart\Contracts\Time\Clock;
use Stewart\Contracts\Time\Duration;
#[Automation(id: 'daily-energy')]
final readonly class DailyEnergy implements App
{
private const int DAYS_KEPT = 7;
public function __construct(
private HaContext $ha,
private Scheduler $scheduler,
private Store $store,
private Clock $clock,
private string $meter = 'sensor.energy_today',
) {}
public function initialize(): void
{
$this->scheduler->runDailyAt('23:55', function (): void {
$today = $this->ha->getState($this->meter)?->getStateAsFloat();
if ($today === null) {
return;
}
$this->store->set($this->createDayKey(0), $today, Duration::hours(24 * self::DAYS_KEPT));
$week = array_sum(array_map(fn(int $daysAgo): float => $this->store->getFloat($this->createDayKey($daysAgo)) ?? 0.0, range(0, self::DAYS_KEPT - 1)));
$this->ha->callService('notify', 'notify', [
'title' => 'Energy',
'message' => \sprintf('Today %.1f kWh, last 7 days %.1f kWh.', $today, $week),
]);
});
}
public function dispose(): void {}
private function createDayKey(int $daysAgo): string
{
$day = $this->clock->getNow()->minus(Duration::hours(24 * $daysAgo))->toDateTime($this->clock->getTimeZone());
return 'day:' . $day->format('Y-m-d');
}
}
apps:
daily-energy:
options:
meter: sensor.energy_today
  • Each day’s value is stored under a key with the date, such as day:2026-01-01, with a time limit of seven days. Older days disappear on their own.
  • The week’s total adds up the last seven keys; a missing day counts as 0.
  • The dates come from the Clock, in Home Assistant’s time zone.
tests/DailyEnergyTest.php
<?php
declare(strict_types=1);
namespace App\Tests;
use App\DailyEnergy;
use PHPUnit\Framework\TestCase;
use Stewart\Contracts\App\AppId;
use Stewart\Contracts\Time\Duration;
use Stewart\Testing\App\AppHarness;
final class DailyEnergyTest extends TestCase
{
public function testTheSummaryAddsUpTheWeek(): void
{
$harness = new AppHarness();
$harness->stores->openAppStore(new AppId('daily-energy'))->set('day:2025-12-31', 9.5);
$harness->ha->seedState('sensor.energy_today', '7.4');
$harness->startApp(DailyEnergy::class);
$harness->advanceTime(Duration::minutes(23 * 60 + 55));
self::assertSame('Today 7.4 kWh, last 7 days 16.9 kWh.', $harness->ha->getLastCall()->data['message'] ?? null);
self::assertSame(7.4, $harness->stores->openAppStore(new AppId('daily-energy'))->getFloat('day:2026-01-01'));
}
}
  • Compare with last week: keep 14 days and add up both halves.
  • Put the week’s total in Home Assistant: expose it as a sensor.