Від телеметрії до рішень: як я будую керування домашньою сонячною станцією

💡 Усі статті, обговорення, новини про DevOps — в одному місці. Приєднуйтесь до DevOps спільноти!

Сто років тут нічого не писав, тож спробую вас зацікавити темою advanced automation.

Останні 1,5 місяця у вільний від дитини і роботи (читайте — вночі) час я розробляю систему управління електроспоживанням будинку. Основна проблема, яку я хочу вирішити: перекласти оптимізацію споживання на рушій прийняття рішень, який буде автоматично вирішувати, коли, як і з якого джерела (сонце, батарея, мережа) заряджати авто, коли гріти воду і скільки можна використати енергії на нагрів, буде приймати до уваги потенційні відключення, зважувати ризики.

І все це має бути побудовано на базі певних стратегій, наприклад, максимізація self-consumption (тобто не брати з мережі), оптимізація витрат (брати з мережі, але коли дешево і нема інших джерел). При використанні даних це дозволяє приймати кращі рішення в моменті, робити постійний evaluation рішень, планувати енерговитрати та оптимізовувати ціну таких витрат.

Це досить комплексна система. Щоб розказати все, буде серія статей, якщо ця вам сподобається.

Давайте почнемо з того, що у нас є:

1. Сонячна станція, що складається з трьох інверторів Victron MultiRS Solar обʼєднаних в трифазну систему.

2. 40кВт акумуляторів Pytes 48100R (8 шт. по 5 кВт).

3. Три поля сонячних панелей: південний схід (12 шт.), південний захід (10 шт.) та північний захід (10 шт.). Загальна потужність поля — близько 14 кВт. Очевидно, що моментальна потужність менша, адже поля рознесені в різні напрями.

4. В системі є трифазна зарядна станція для машини від Victron. Розміщена на inverter ac-out (тобто за інвертором).

5. Будинок опалюється тепловим насосом повітря-вода Viessmann Vitocal 100-S тепловою потужність 16 кВт, електрична потужність 5 кВт, однофазний.

6. Є багато лічильників енергії, в основному це Shelly-пристрої. Також стоїть ввідний лічильник Victron на вході інверторів.

Тепер давайте трошки про систему.

Основна мова розробки — C#, .net 10. Хоститься локально на сервері в Docker-контейнері, розділена на три окремі сервіси. Система використовує:

  • Influx для зберігання телеметрії в час;
  • Postgress для збереження даних прогнозів, налаштувань системи, інтеграції;
  • Seq як простий сервіс логів.

Edge.Web

Це простий сервіс .NET MVC, який візуалізує дані, дозволяє налаштовувати систему, відстежувати її дії в часі, трейсити прийняті рішення та вибирати режими роботи. Він також надає широку аналітику в часі та стан системи в режимі реального часу.

Edge.Host

Хост-сервіс телеметрії та рішень. Це головний runtime-процес системи. Саме він збирає телеметрію з енергосистеми, підтримує актуальний стан установки, запускає фонові інтеграції та виконує оперативну логіку керування.

1. Збір даних у реальному часі з Victron реалізовано через підключення до MQTT-сервера на Victron Cerbo GX (це такий управляючий пристрій у Victron). Edge.Host підписується на ключову телеметрію: генерацію від сонця, споживання, роботу батареї, мережу та EV-стан. Ці повідомлення він не просто приймає, а нормалізує в єдину модель стану системи.

2. Для історії та аналітики Edge.Host агрегує телеметрію в похвилинні buckets і зберігає її в InfluxDB. За рахунок цього ми маємо не лише «поточне значення зараз», а й детальну похвилинну картину по основних енергетичних потоках: сонце, мережа, споживання, батарея, зарядка авто.

3. Поверх цього Edge.Host тримає live-зріз системи і кожні 30 секунд запускає decision loop. На цьому циклі сервіс оцінює поточний стан установки, підтягує прогнози й налаштування та вирішує, як система має поводитися далі, оновлює та підтримує State Machine всієї установки

4. Окремо Edge.Host піднімає оперативні HTTP endpoints: для live-телеметрії, статусу системи, ручного refresh прогнозів, перегляду decision traces і технічної діагностики. Тобто це не просто ingestion-сервіс, а центральний orchestration layer.

Host інтегрує наступну телеметрію:

  • MQTT life телеметрію з Cerbo GX.
  • Телеметрію з підключених пристроїв Shelly (тут pull кожні 5 сек, інтервал налаштовується для кожного пристрою).
  • Телеметрію з підключених інтеграцій, наприклад для теплового насосу через Viessmann API.

Host управляє сонячною станцією через Modbus TCP, через нього також читає актуальний стан пристроїв та перевіряє виконання команд.

Edge.Forecast.Worker

Є центральним вузлом прогнозування на наступні періоди. Якщо Edge.Host відповідає за live-стан системи та оперативні рішення, то worker відповідає за регулярну побудову прогнозів і підготовку плану на добу вперед (насправді до кінця поточного дня + наступний день).

1. У ньому живе production-інференс ML-моделей. Worker завантажує підготовлені Python-моделі LightGBM і запускає їх уже з .NET через нативну LightGBM-бібліотеку. Тобто навчання моделей і runtime-виконання розділені: тренування відбувається окремо, а в проді використовуються зафіксовані артефакти. Для тренування використовуються дані, що зібрані системою з телеметрії та різних API, які далі формуються в dataset для 3х різних моделей.

2. На кожному циклі worker бере історичну та актуальну телеметрію й будує 24-точкові погодинні прогнози за ключовими величинами: споживання, SOC батареї та PV-генерації. По суті, це day-ahead forecast layer, який готує енергетичну картину на наступні години.

3. Далі Edge.Forecasts.Worker зберігає ці прогнози в PostgreSQL як окремі версіонізовані snapshots. Коли є повний і валідний набір погодинних прогнозів, він на їх основі публікує operational schedule, який вже може використовуватися далі в системі.

4. Окремо worker підтримує ML data pipeline: оновлює датасети для активних моделей. Кожен день вночі він доповнює датасет свіжими даними за вчора.

Якщо дуже коротко, то Edge.Forecasts.Worker це окремий forecasting engine: він бере телеметрію, проганяє її через ML-моделі, зберігає прогнози і публікує готовий погодинний план для всієї енергосистеми. Також він вигрібає прогнози зі сторонніх джерел:

  • Погоду тягнемо з Open Meteo.
  • Через Victron VRM API тягнемо прогноз по споживанню та сонцю. Це робиться як fall-back стратегія та для порівняння різних прогнозів. Я можу вибрати, що саме використовувати в системі — ML прогноз чи прогноз, який будує сам Victron.

Прогнози оновлюються кожну годину, кожну годину перебудовується Daily Schedule, який на картинці вище. Кожне оновлення прогнозу = новий snapshot. Якщо по якійсь причині не вийшло створити новий snapshot, система використовує попередній успішний, але така проблема логується, а система піднімає рівень песимізму в прийнятті рішень.

Думаю, з оглядом сервісів ми завершили. В цій статті хочу розповісти, як саме будується ML-прогноз, бо це база (фундамент, основа) роботи системи. Без цього рішення самі по собі будуть не валідні.

ML прогнозування

В системі тренуються три основні моделі: SOC_1h, Consumption_1h, PV_1h. З назв ясно, що вони всі погодинні. У мене була ідея будувати коротші інтервали, типу 15 хв, але на практиці виявилося не дуже практично, так як виконання прогнозу все одно можна відстежувати в реальному часі.

Для прогнозування використовую LightGBM — це відносно проста для використання ML-модель, яка використовує ансамбль дерев рішень, побудованих методом gradient boosting. Не жере памʼять (всі три моделі в рантаймі тягнуть до 1GB памʼяті разом), а це важливо, коли крутиш це все на лімітованих ресурсах.

Навчання розділено від runtime, тобто я запускаю навчання вручну, нові артефакти створюються, а далі приймаю рішення на базі результатів навчання: якщо MAE (Mean Absolute Error) та RMSE (Root Mean Squared Error) покращилися, то йде в прод.

Модель SOC_1h

В цій прогнозній моделі використовуються наступні features:

monthномер місяця (1-12)
day_of_weekномер дня тижня (1-7)
hour_of_dayлокальна година доби (0-23)
is_daylight0/1 індикатор світлої доби
battery_soc_lag_1hстан заряду батареї годину тому
battery_soc_last_15mстан заряду батареї 1 хв тому
net_balance_next_hourбаланс енергії в наступну годину (планована генерація — плановане споживання)
pv_to_battery_last_1hкількість енергії що з сонця перетікла в акумулятор за останню годину
hourly_pv_forecast_kwhпрогноз сонячної генерації на поточну годину прогнозування
grid_to_battery_last_1hкількість енергії, що перетікла з мережі в акумулятор за останню годину
net_battery_energy_last_hourбаланс енергії акумулятора (заряд мінус розряд) за минулу годину
battery_charge_energy_last_15mкількість енергії яка пішла в акумулятор за останні 15 хвилин
battery_discharge_energy_last_15mкількість енергії яка пішла з акумулятора за останні 15 хвилин

Такий feature-set дає достатньо даних для того, щоб реагувати на зміни в системі та давати виключно якісний прогноз. Наприклад, графік за один з днів:

Видно, що модель (пунктир) зреагувала на розряд батареї вночі (зарядка авто йшла частково з батарейки) і майже 1-в-1 слідує за фактичними даними. Прогноз перераховується погодинно, кожен новий прогноз — новий snapshot. Можна відстежити всі дані, які були вибрані для прогнозування, експортувати весь feature set або видалити цей прогноз (він буде регенерований автоматично, якщо Worker не знайде активний, діючий, опублікований snapshot на поточну годину).

На даний момент дата сет моделі для тренування налічує 1032 рядки, що дорівнює 42 дням історичних даних.

Модель Сonsumption_1h

В цій прогнозній моделі використовуються наступні features:

FeatureValue
monthномер місяця (1-12)
is_weekend0/1 індикатор вихідного дня, бо там є залежність: на вихідних споживання менше
day_of_weekномер для тижня (1-7)
hour_of_dayлокальна година доби (0-23)
consumption_lag_1hспоживання будинку за минулу годину
consumption_lag_2hспоживання будинку позаминулу годину
consumption_lag_24hспоживання будинку в цю саму годину 24 години тому
ev_charge_sum_last_1hвитрата енергії на зарядку авто в минулу годину
ev_is_charging_last_15m0/1 чи машина заряджалась останні 15 хв
weather_temperature_2m_cтемпература повітря в прогнозну годину

Найбільшими драйверами в цій моделі є, звичайно, витрати на зарядку машини. Ось приклад реакції моделі на зарядку машини:

Синім — фактична витрата енергії на заряджання авто.

Так як споживання — дуже волатильне, то погрішність моделі на даний момент складає близько 7% від фактичного в середньому. Наприклад, за вчора прогноз — 69 кВт, а факт — 75 кВт. А позавчора 58 кВт vs 59 кВт. Неможливо передбачити умовне прання, посудомийку і т. д.

На даний момент датасет моделі для тренування налічує 1032 рядки, що дорівнює 42 дням історичних даних.

Модель PV_1h

В цій прогнозній моделі використовуються наступні features:

FeatureValue
monthномер місяця (1-12)
day_of_weekномер для тижня (1-7)
hour_of_dayлокальна година доби (0-23)
clouds_last_hour% хмарності за минулу годину. ці дані йдуть з прогнозу погоди
pv_actual_last_hourфактична генерація за минулу годину
radiation_last_hoursolar radiation за минулу годину
pv_forecast_last_hourML прогноз по генерації за минулу годину
visibility_next_hour_m«видимість», тобто прозорість атмосфери
weather_code_next_hourпогодний код на наступну годину, який надає провайдер погоди
clouds_forecasted_next_hour% хмарності на наступну годину
radiation_forecasted_next_hoursolar radiation на наступну годину
relative_humidity_next_hour_pctвідносна вологість в наступну годину
direct_normal_irradiance_last_hourкількість прямої сонячної енергії в Вт/м2 за минулу годину
direct_normal_irradiance_next_hourкількість прямої сонячної енергії в Вт/м2 на наступну годину
precipitation_probability_next_hourймовірність опадів на наступну годину

Всі сонячні та погодні дані, крім факту і прогнозу генерації, беруться з прогнозу Open Meteo. Worker погодинно оновлює прогноз свіжими даними, які далі використовуються в прогнозуванні.

Це — найбільший датасет: у ньому 9768 рядків, тобто 407 днів даних. Звідки стільки даних, якщо система працює лише 1,5 місяця? Я витягнув їх з VRM API, погодинну історію за останній рік і доповнив своїми даними. Віктрон зберігає дані по установці і є можливість витягнути їх, це дозволило доповнити історичний горизонт.

PV forecast не суперточний в моменті, тому що сонячна генерація залежить від дуже багатьох факторів, які неможливо передбачити. Але дуже точний на рівні дня, враховуючи, що десь він себе переоцінив, а десь навпаки — був сильно песимістичним.

Зазвичай прогноз промахується в меншу сторону, тобто генерації трохи більше. Наприклад, вчора прогноз — 52 кВт, факт — 59 кВт, позавчора (був складний день по сонцю) прогноз — 27 кВт, факт — 32 кВт.

Замість висновку. І що далі

Сподіваюсь, тему я зачепив цікаву. Все в одну статтю не вкладеш, тому далі думаю будуть наступні статті:

  • Оркестрування прийняття рішень.
  • Інтеграція різних пристроїв.

Ну, як мінімум, це. Дякую всім за читання і буду радий відповісти на питання (але не обіцяю, що швидко відповідатиму).

👍ПодобаєтьсяСподобалось16
До обраногоВ обраному4
LinkedIn
Ctrl + Enter
Ctrl + Enter

Цікаво продовження про оркестрування та інтеграції.

Файна стаття, Євгене! Приємно бачити твою статтю тут у нас)

Гарно!

Підписатись на коментарі