Як я підтримую та розвиваю ElectricityOff
Вітаю, мене звати Зореслав Гораль. Я FrontEnd розробник і це продовження першої статті про розробку ElectricityOff — застосунку для моніторингу вимкнень електроенергії. Стаття буде цікава практично всім, оскільки в ній мало технічних деталей, а більше про хронологію розробки, появу нових фіч та взаємодію з кристувачами. Хто ж розробляє власні продукти, можливо знайдуть для себе якісь інсайти, тощо. Раджу ознайомитися з першою частиною, а тоді переходити до цієї. Отже поїхали.
Події що відбулися після першої статті (не в хронологічному порядку)
Після описаного в першій статті відбулися деякі наступні події, котрі вплинули на зміни в застосунку. На жаль, деталі та хронологію вже не пригадаю, тому надалі я їх просто коротко опишу, але все ж таки буду старатися писати в хронологічному порядку.
Через деякий час Google таки дозволив запуск застосунку в ElectricityOff PlayMarket. Але різкого приросту користувачів, які б прям суттєво перевищили кількість ElectricityOff AppStore не відбулося.
Push-нотифікації
Декілька раз були проблеми з нотифікаціями. Взагалі, зараз це найбільш технічно складна частина застосунку і в майбутньому проблеми з ними знову будуть. Не пригадаю, що було саме тоді, але здається пофіксилося розбиттям на чанки.
Банер
Вже й не пригадаю яка критична помилка була і не було можливості повідомити користувачів про неї. Після фіксу було вирішено додати простий банер, котрий би відображав просто зображення, налаштовувався на рівні БД та був клікабельним. Планував, що пізніше окрім повідомлення про критичні помилки зможу його використовувати для реклами. Правда, наразі концепція застосунку змінилося і реклами не передбачається. А банер час від часу використовую, наприклад на свято св.Миколая, чи Олімпійських ігор.

Системне повідомлення
Після проблем з нотифікаціями та задвоєними повідомленнями я вирішив, що корисно було б мати можливість повідомляти користувачів про такі ситуації. Був створений новий тип push-нотифікації — поломка. Таке повідомлення редагувалося на рівні БД і запускалося вручну. Повідомлення можна було надіслати усім, або ж користувачам, в котрих вибрані черги певних постачальників. Правда я користувався ним тільки пару раз. Не люблю коли мене спамлять навіть такими повідомленнями.
30-хвилинний інтервал
В якийсь момент, постачальники перейшли на 30 хв інтервал вимкнень. Якщо раніше вимкнення та ввімкненя відбувались рівно по годинах, наприклад 10:00 — 12:00, то тепер став можливим варіант 10:30 — 12:30. Пригадаю, що тоді це зачепило майже всі схожі застосунки та боти. План фіксу був наступний — фікс на сервері, швидкий випуск нової версії для обох платформ. Перехід на підтримку 30 хв зайняв пару днів.
Зміна назв черг та інші фанові штуки
Якщо раніше, кожна область мала своє найменування черг (груп), то в якийсь момент Укренерго оголосило, що всі перейдуть на 6 черг з

В якийсь момент було бажання розвивати застосунок, але що туди додавати не приходило в голову. Не пригадаю як виникла ідея відображати час сходу та заходу сонця. Здається, наш дизайнер Макс був проти, але я зробив та задеплоїв бета-версію. І після того він переробив дизайни в Figma. Забігаючи наперед, скажу, що я був дуже здивований тим, що люди користуються цією фішкою.

В застосунку є баг, коли час сходу чи заходу сонця може перекриватися інтервалами вимкнень і користувачі просили це виправити. А працює це дуже просто — щодня перед 24:00 джоба в Convex викликає публічне АРІ та зберігає час сходу та заходу сонця у власну колекцію, а застосунок вже використовує ці дані. Тут правда є деяка неточність, оскільки дані беруться для Києва. Але ці виправлення поки не в пріоритеті. Також була додана підтримка темної теми і переїзд каналу підтримки з Telegram на WhatsUp.

Статуси постачальників
В той час в нас було вже три постачальника — Прикарпаття, Чернігів та Львів. Для Львова ми розпізнавали зображення. Якщо з першими двома все було стабільно, то Львів часто міняв зображення, Олег не встигав адаптовувати бекенд і застосунок переставав відображати дані. То ж було вирішено додати статуси для постачальника та відображати їх користувачеві. То ж тоді для Львівобленерго в нас майже постійно відображалось «зламалось, вже ремонтуємо».
Рік без вимкнень
Біля року чи навіть більше вимкнень не було. Всі забули за застосунок, в тому числі і я. Настільки забув, що навіть не продовжив хостинг. Convex бекенд був переведений на безкоштовний план, оскільки працював над ще одним Pet-проєктом. Коли вимкнення відновилися, виявив що в мене закрився хостинг через неоплату. Служба підтримки провайдера не змогла відновити аккаунт, то ж довелося все розгортати по новому. На щастя, код лежав на Github і там же була мінімальна документація по розгортанню, тож на відновлення потратив менше доби. Все запрацювало дуже швидко.
Злетів Прикарпаттяобленерго, переїзд на VPS
В один момент для Прикарпаттяобленерго перестали відображатися дані. Дивним було те, що у колег з боту Знеструмко дані відображалися. Вони ж мені порадили український VPS хостинг, куди я мігрував частину свого АРІ. Виходив дещо архітектурний спагетті-код, то ж було вирішено перенести все АРІ на новий VPS хостинг і дещо змінити архітектурно.
Підключення нових постачальників
То був час підключень нових постачальників. Статистика скачувань, користування, рейтинги зростали прямо на очах. Бувало, що вдавалося підключати навіть
Немає єдиного стандарту оприлюднення графіків вимкнень. Хтось з постачальників використовує АРІ, хтось відображає html-таблицями, текстом, а деякі навіть викладають таблиці зображеннями. То ж я знайшов спосіб парсити зображення за допомогою JavaScript. Якщо ж зображення не міняли розмір, колір та розташування — то це успішно працювало. Правда доводилось дуже часто адаптовувати скрипти під зміну розмірів, форматів, тощо. Старався максимально швидко реагувати на повідомлення від кристувачів в соцмережах та групі підтримки WhatsUp.
Нова архітектура push-нотифікацій
В якийсь період знову перестали нормально працювати push-нотифікації. Аналіз показав, що знову ліміти. На цей раз функції Convex повертали більше 32 тис записів і перевищували ліміти. Довелося в кожній функції додавати підтримку pagination. Врешті-решт архітектура push-нотифікацій була повністю перероблена. Ось так вона працює зараз.

Якщо спростити, то це можна описати так, що є два незалежних процеси:
Процес 1
- перевіряє кожні 10 хв чи є зміни в інтервалах вимкнень (появились, змінились, появились на завтра, тощо) та кожні 15 хв чи будуть ввімкнення вимкнення і по яких чергах
- формує запис для колекції повідомлень
- додає цей запис зі статусом «ненадіслано»
Процес 2
- перевіряє кожної хвилини колекцію повідломлень
- якщо є ненадіслані, то бере в роботу перше ненадіслане (ставить статус «в роботі»)
- підшукує користувачів для даного повідомлення відповідно до вибраних користувачем черг
- формує масив з текстом повідомлення для push-нотифікацій (назва черги береться з налаштувань користувача)
- надсилає та ставить статус «виконано» або «помилка» у разі помилки надсилання
Варто зазначити, що щодня перед 24:00 спрацьовує Convex job котра видаляє з колекції записи користувачів, котрим повідомлення не було доставлено за причиною помилки видалення застосунку.
Проблеми підтримки багатьох постачальників
Кількість підключених постачальників росла як гриби. Наразі підключено 21 постачальник електроенергії. З ростом кількості постачальників зросло і навантаження на підтримку. Періодично через різні причини (в основному через зміни в форматах подачі даних зі сторони постачальників) синхронізація даних ламалася. Доводилося оперативно все виправляти. Це було важко.
Соцмережі та сайт
Наразі застосунок представлений в Threads, LinkedIn, Facebook та Instagram. Чат підтримку відкрито в WhatsUp (куди ми переїхали з Telegram). Найбільш активно я веду Threads — там найбільше користувачів. Тому, якщо бажаєте першими дізнаватися про нові релізи, фічі та звісно баги — підписуйтесь. Також було розроблено маркетинговий сайт застосунку (признаюсь чесно — він не SEO-friendly але переробити на NextJs руки не доходять).
Зміни в налаштуваннях
Завдяки власне Threads було внесено багато побажань від користувачів, зокрема:
- розширені налаштування push-нотифікацій (період «нетурбування», можливість вимкнень сповіщень для окремих черг)
- власні назви черг, та використання власних назв в push-нотифікаціях
- перемішування кольорів черг
- відображення сумарної кількості годин за добу без електропостачання
- відображення історії змін вимкнень
Одного разу один користувач ну дуже просив збільшити кількість черг, що можуть одночасно відображатися з 5 до 6. Я для таких запитів зазвичай прошу привести конкретні пояснення для чого, сценарії використання, тощо. Якщо людині просто цікаво чи для фану, то я таке не роблю. Якщо ж є реальні причини — то зазвичай роблю відповідні зміни в наступному релізі. Так от, та людина зізналась як є, що працює в Обленерго і йому потрібно встигати між вимкненнями переміщатися між чергами і для зручності він використувує застосунок. Звичайно, що в наступному релізі я збільшив кількість черг.
Як я «попав» через любов до статистики
Пригадую, що був дуже активний тиждень долучення нових користувачів. Як раз синхронізувався з Хмельницькобленерго. Щодня підключалося більше тисячі користувачів. Трекати в Google аналітиці мені набридло, то ж я вирішив винести статистику на сайт — кількість користувачів за сьогодні, загалом та за постачальниками. І зробив я це максимально «тупо» — повністю перераховував всі значення після кожної реєстрації користувача. Наступного для графік використання ресурсів Convex мене, м’яко кажучи шокував — за пів-дня використано 1 Тб трафіку. А користувачі продовжували активно додаватися — майже щохвилини пару нових користувачів. То ж я постав перед дилемою — зупинити застосунок і шукати причину чи залишити все як є і шукати причину. Я розумів, що у випадку зупинки я втрачу дуже багато користувачів назавжди і рейтинг застосунку впаде. На щастя, причина була швидко знайдена і метод підрахунку статистики переблений — наразі він оновлюється кожної години.

Шліфування UI/UX
З кожним релізом окрім критичних та корисних виправлень я старався вносити покращення з точки зору UI/UX. Інколи цих змін не помічаєш, тому що все працює і все логічно і інакше й не може бути, але вони працюють не «з коробки».
Найбільш цікаве і значне оновлення як на мене, це UI/UX-концепція вкладки «Графік», котра є основною і тією з котрою найбільш частіше взаємодіє користувач.
Працюючи над вкладкою «Графік», я сфокусувався не на нових фічах, а на зменшенні когнітивного та фізичного навантаження на користувача.
Ключова ідея проста:
інтерфейс має приводити користувача до актуального контексту сам, без зайвих тапів, свайпів і ручного скролу.
Що це означає на практиці:
- При будь-якому переході на вкладку «Графік» автоматично вмикається вигляд «Сьогодні» та відбувається плавний скрол до поточного часу.
- Перехід з push-notification про подію сьогодні — поводиться так само: користувач одразу бачить релевантний момент.
- При переході на «Завтра» скрол автоматично позиціонується на 00:00 — без потреби шукати початок дня.
- Перехід з push-notification про подію завтрашню — поводиться так само: користувач одразу бачить релевантний момент.
- Повторний тап на вкладку «Графік» працює як швидке повернення до «зараз».
- Свайп між «Сьогодні» та «Завтра» виправлений і супроводжується м’якою, не відволікаючою анімацією.
Маленька червона точка на кнопці «Завтра» привертає увагу та сигналізує, що вже є дані на завтра.
В результаті користувачеві не потрібно робити зайвих рухів, а анімація допомагає зрозуміти куди його перенаправляє застосунок.
Для отримання більшої кількості відгуків було додане діалогове вікно, котре показувалось один раз через 2 тижні після завантаження застосунку. Якщо користувач закривав його, то воно більше йому не набридало. Якщо ж мав що і хотів сказати, то 2 тижні якраз достатньо, щоб сформувати думку про застосунок.
База від Моно
Кількість користувачів зростала, на підтрику лягало більше навантаження, потрібно було знаходити ресурси для покриття вартості хостингів, підписок і т.д. Розглядались варіанти — реклама, про-версії і т.д. Але в результаті перемогла модель добровільних донатів. Для цього була використана База від Monobank.
В застосунку було додано маленьку піктограмку у вигляді сердечка, а також через 2 тижні після користування додатком появлявся банер з пропозицією донату.
База від Моно розрахована більше на блогерів, стрімерів, контент-кріейторів. Та врешті-решт вони таки дозволили мені її використовувати.

Власне після підключення Бази я вирішив остаточно сформувати офіційну позицію щодо розвитку застосунку:
Офіційна позиція щодо розвитку ElectricityOff
- ElectricityOff був і залишається повністю безкоштовним.
- У застосунку немає реклами, і так буде надалі.
- Усі нові функції, оновлення та покращення — завжди безкоштовні для всіх користувачів.
- Відкрито Базу від Monobank для тих, хто хоче підтримати роботу серверів та розвиток застосунку.
- Донати — цілком добровільні, не дають жодних обмежень чи привілеїв.
Convex ліміт на виконання зовнішніх АРІ
Зовнішні АРІ, котрі збирали інформацію щодо відключень для нових постачальників були складними, оскільки для деяких постачальників потрібно було викликати АРІ для кожної з 12 черг і потім об’єднати все в одну відповідь. Користувачі почали жалітися, що для певних постачальників затосунок працює нестабільно — дані то зникали, то знову появлялися, або залишалися неактуальними після змін зі сторони постачальника. Аналіз виявив, що у Convex існує таймаут на виклик зовнішнх АРІ — 10 с. Тому деколи виклики проходили добре, а деколи з помилкою таймаута. Було вирішено повністю змінити схему, а саме:
- Collector — збирає кожні 10 хв дані від постачальників та записує в MongoDB
- Для Convex написано просте API, котре тільки повертає дані з колекції і виконується дуже швидко
Також використано більш декларативний підхід — URL сервісів для отримання даних від постачальників та ID постачальника зберігалися в окремій колекції. Була застосована декомпозиція — в proxy API залишилось тільки сервіс proxy, а для кожного постачальника створено окреме API, котре спілкується з сайтом постачальника через proxy API та деплоїться на Vercel задля зручності розробки та швидкості деплою. Наразі цю міграцію завершено не повністю.

Зараз процес підключення нового постачальника виглядає наступним чином:
- Створення АРІ для отримання даних з сайту постачальника
- Розгортання за допомогою Vercel
- Додавання постачальника та його черг в базу Convex
- Додавання endpoint та providerId в базу MongoDB
Відгуки та рейтинги
На час написання статті рейтинги PlayMarket — 4.6 та AppStore — 4.8. Застосунок двічі піднімався на

Щодо відгуків. Загалом більшість позитивні та конструктивні, хоча бувають також смішні та хамські. Щодо останніх — перше бажання нахамити у відповідь, але я стримую себе і відповідаю максимально коректно наступного дня. Зазвичай після такої відповіді користувач редагує свій відгук. Часто буває коли люди не розуміють, що застосунок не має жодного відношення до будь-яких ДТЕК чи Обленерго і у відгуках сваряться щодо реальних графіків. Нижче пару прикладів:



iOT
В якості експерименту зробив відображення графіку на M5Stack Core lnk. Можливо комусь буде цікаво. Наразі там захардкоджено все включно з назвою WiFi мережі та паролем. Прилад кожної хвилини виконує запит до АРІ та оновлює інформацію.

Висновки, плани і т.д.
Розробка успішного продукту це однозначно дуже крутий досвід. І як виявилось це 20% кодингу та 80% підтримки, маркетингу, планування, спілкування з користувачами, тощо. Зробити продукт один раз і не підтримувати мабуть не вийде — хіба це щось дуже просте.
Глобально хочеться завершити цей проєкт, оскільки підтримка вимагає багато часу. Хоча наразі закривати не планую, оскільки застосунком користується майже 80 тис користувачів, а це — відповідальність.
Також хочеться почати свій проєкт, де я б все контролював без зовнішніх інтеграцій та не залежав від сторонніх сервісів.
Повноцінно так і не були реалізовані віджети, хоча про них дуже багато запитували. Інтеграція нативного коду з React Native виявилась складною, вчасних оновлень віджетів так і не вдалося досягти. Можливо повернуся до цього, але поки не планую. Перша реалізація віджетів так і живе в бета-версії. Також є ідея нової гри, але поки дальше ідеї це не просунолося.
Дякую, що дочитали. З радістю відповім на ваші коментарі.
Сподобалась стаття? Підписуйтесь на автора, щоб отримувати сповіщення про нові публікації на пошту.

7 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів