Захотелось оживить рабочий стол, но обычные живые обои либо быстро надоедали, либо слишком сильно грузили систему. В итоге решил написать свой проект с нуля - 🧬Syntropy. Это интерактивные неоновые обои, которые превращают рабочий стол в живую цифровую экосистему.
В основе лежит процедурная симуляция эволюции. Прямо под иконками автономные ИИ-команды рождаются, мутируют и воюют за территории. Движок постоянно просчитывает случайные мутации, поэтому цвета фракций и рисунок сражений никогда не повторяются. При этом симуляция интерактивна. Кликами по экрану можно спавнить новые клетки, искусственно влияя на баланс сил. Из визуальных эффектов добавил мягкое свечение, физику микрочастиц и параллакс при движении курсора. Все параметры вроде скорости эволюции, размеров ячеек и яркости настраиваются через меню в системном трее.
Основной упор я делал на оптимизацию, чтобы программа работала даже на слабых ноутбуках. Проект написан на C++17 и SFML без тяжелых готовых движков, а эффекты обрабатываются через кастомные шейдеры. Для игр и полноэкранных приложений предусмотрена умная автопауза. В этот момент обои полностью останавливают расчеты, снижая нагрузку на процессор и видеокарту до абсолютного нуля.
Программа полностью портативная, не требует установки и работает на Windows и Linux. Также сделал бесшовную поддержку нескольких мониторов и автоматическое сохранение карты клеток, так что после перезапуска системы симуляция продолжается с того же места.Делал для себя, но буду рад, если кому-то тоже зайдет.
Когда то я думал, вот вырасту и стану взрослым... Мышление поменяется, буду совершать поступки какие то взрослые, вести себя буду "по взрослому". Вырос, 40+, я тот самый взрослый, ничего не поменялось, нет каких то "взрослых" мыслей, поступков, нет критериев взрослости. Работа, дом, машина, дача, ребенок, а взрослости нет.
Большое совещание министерства промышленности. За столом взрослые люди за каждым из которых, как минимум, большое предприятие. Замминистра задаёт вопрос прямо: "Что мы можем с этим сделать?".
Незримый метроном отсчитывает паузы.
Вежливая пауза после заданного вопроса.
Прошла.
Пауза, которую люди берут на обдумывание ответа.
Прошла.
Пауза на принятие ответственности за первое высказывание.
Прошла.
Все. Неважно что будет сказано дальше, это будет сказано только что бы заполнить звенящую тишину. Представители науки и промышленности молчат, ни у кого нет готового решения. Все умеют делать хорошо, дорого и медленно. Сейчас надо по другому.
Уже не за столом, а в более неформальной обстановке взрослый человек стоящий далеко надо мной в цепочке управления говорит с другим взрослым человеком, который может предоставить финансирование:
– Мы можем сделать, срок несколько месяцев.
– Делайте, сразу два образца.
Задача спускается вниз, не как обычно – через бумаги с обилием подписей, а моментально, через личное общение начальника с подчиненным. В итоге, мы единственные в стране, кто делает.
Некоторые вещи на своей работе я делаю быстрее и лучше других. Не повод для гордости, просто так сложилось. Мне показывают схему. Крупные мазки, всего два листа - основное назначение и обеспечение. Интересно. Я начинаю улыбаться. Готовлюсь к разбегу.
– Надо просто, что бы работало?
– Да, все по необходимому минимуму.
Разминаю лапки.
– Из говна и палок?
– Да, и смотри что бы палки не подорожали.
Бегу, и волосы назад.
– Приемка?
Молчаливое отрицание.
Молчаливый вопрос.
– Сдаем сами себе, нам доверяют
Ленточки с надписями ОТК, МВК и некоторыми другими разрезаны, я взмываю вверх над бездной. Зависаю на секунду.
– ТЗ?
Но ответ я знаю и так
– Нет ТЗ ни у нас, ни у тебя, если нужно напиши себе сам.
Я радостно плюхаюсь в бездну разработки.
– У вас тут в схеме ошибки…
Диссонанс от уровня ответственности этой работы и моей радости от процесса вынуждает меня написать этот текст.
Почему ответственность не давит? Все взрослые такие? Или это я такой? Или я до сих пор не взрослый?
Наверное это неважно. У меня сжатые сроки, а слепленной в спешке схеме нужны очередные правки.
P.S. Тег «моё» — рассказ написан мной, это не личный опыт.
Две недели назад публиковал первый пост о своем компоненте. Ну, теперь кажется, что там был простенький и неуклюжий набросок, по сравнению с тем, что умеет и как работает сейчас. Функционала не прям много, старался не отходить от целей и задач, но все-таки много инструментов появилось. Ненадолго передаю слово Клоду, он даст дайджест изменений:
- Новый режим заливки «Свет по источникам»: весь дом тёмный, включённые лампы дают пятна света своего цвета (RGB или температура), свет проникает через дверные проёмы в соседние комнаты. Радиус свечения настраивается для каждой лампы.
- Иконки отражают состояние как в HA: двери/окна открыты-закрыты, лампы горят своим цветом, тревоги (дым, протечка) пульсируют красным. Вместо иконки датчика можно показывать само значение (температуру, влажность).
- Подписи комнат превратились в карточки: имя + температура, влажность, сигнал Zigbee, свет («1 из 3»). Карточки можно двигать и растягивать.
Управление прямо с плана
- Лампы, люстры и группы света переключаются кликом по умолчанию — ничего настраивать не нужно. Правый клик по любому устройству — карточка HA.
- Выключатель на плане может управлять любым набором ламп (даже если сам он «тупой» или это кнопка-пульт): клик переключает все разом, значок показывает их состояние.
- У двери с замком в карточке появилась кнопка «Открыть/Закрыть замок». Сам замок кликом с плана не переключается никогда — только осознанной кнопкой.
Редакторы
- Три отдельных редактора вкладками: План (комнаты, двери-окна), Устройства (значки), Подложка (линии, фигуры, надписи — чистый декор). Просмотр — безопасный режим по умолчанию: ничего нельзя случайно сдвинуть.
- Рисование прокачано: объединение и разделение комнат (в т.ч. ломаной линией), комнаты внутри комнат (колонна, кладовка), «виртуальные стены» — условные границы зон, через которые проходит свет (рисуются пунктиром).
- Помощник выравнивания: направляющие линии от соседних объектов и подсветка углов, кратных 45° — лампы легко выстроить в ряд.
- Двери и окна ставятся кликом по стене с превью, знают свой датчик открытия и замок, рисуются открытыми/закрытыми вживую. Линейка показывает длину и угол в реальных метрах/футах.
Мелочи, которые заметите
- Новое устройство в HA появляется на плане с красной точкой — пока не откроете его настройки.
- План запоминает, где вы были: этаж и редактор восстанавливаются после закрытия вкладки.
- Значок-ссылка у имени комнаты ведёт в зону HA.
В планах - адаптация под планшеты, для постоянного использования в настенном режиме.
Все началось с рабочей задачи по реализации весьма специфичной web-панели мониторинга и управления различным оборудованием, в которой нужно было получать данные и отправлять команды по разнообразным сценариям (периодический опрос, подписка на websocket-события, https-запросы и т.д.), а также выводить состояние и графики в реальном времени, динамически комбинируя различные источники данных в разных виджетах.
Кроме того, у панели было предусмотрено несколько настраиваемых режимов работы, которые переключались по запросу пользователя, что требовало массового управления маршрутами потоков данных внутри системы.
В первой итерации с использованием RxJS получилось много неструктурированного и сложно поддерживаемого кода, так как архитектура на RxJS вынуждала императивно описывать перестроение топологии при изменении правил маршрутизации «на лету». В нашем специфичном кейсе с динамическими виджетами это приводило к сайд-эффектам и сложностям в отладке. Кроме того, местами размывалась строгая типизация и мы лишались compile-time гарантий. Так появилась идея разработать собственное решение на основе альтернативной концепции — модели графа потоков данных.
В результате получившаяся модель продемонстрировала предсказуемое поведение и низкую связность компонентов, а кодовая база сократилась на ~30% и приобрела более декларативный вид. Убедившись в эффективности решения, мы решили оформить его в виде отдельной библиотеки с открытым исходным кодом — Transferum.
И что, получилась просто еще одна реактивная библиотека?
Не совсем. Классические FRP-библиотеки (RxJS, Bacon, Most) построены вокруг единственного примитива (Observable). Transferum же основан на композиции различных типов узлов с явно определенным поведением.
Каждый узел в графе потоков распространения данных явно декларирует свои способности: может ли он принимать данные через push, отдавать через pull, распространять полученный сигнал подписчикам, опрашивать источник, фильтровать, блокировать поток и т.д.
Объявленные узлом возможности являются одновременно флагами для использования в runtime и compile-time гарантиями наличия соответствующих методов, определяющих его поведение.
Ключевая идея: поведение системы описывается как композиция независимых возможностей, которые одновременно определяют тип, реализацию и правила взаимодействия.
Transferum предоставляет четыре слоя абстракции:
Трансферы — узлы графа (каналы, поллеры, мапперы, буферы, разветвители и концентраторы, реализации debounce, throttle, switchMap и т.д.).
Мосты — ребра графа — управляемые вентили между узлами с динамической маршрутизацией и гейтингом.
Операторы — stateless-трансформаторы и фильтры данных (используются трансферами, отвечающими за конвертацию данных).
Билдеры — fluent-конструкторы композитных трансферов из цепочек трансферов-примитивов.
Концептуальная и архитектурная основа — capability flags system. Каждый трансфер реализует CommunicationContractInterface — набор булевых флагов, определяющих его возможности.
Флаги isPushable, isPullable, isSubscribable, isGate и другие — это не просто свойства объекта. Это метаданные, которые:
Определяют TypeScript-интерфейс трансфера на этапе компиляции.
Управляют стратегией связывания с другими трансферами в рантайме (с помощью функции linkTransfers()).
Обеспечивают совместимость в билдерах без приведений типов.
Один набор флагов — три потребителя. Это единый источник истины для всей системы.
Когда флаг равен true, соответствующий метод входит в TypeScript-интерфейс трансфера. Это позволяет предоставлять трансфер пользователю вот так:
Transfer<T, [Pushable, Pullable, Subscribable, Triggerable]> // гомогенный трансфер: T -> [ Transfer ] -> T
1. Трансферы не знают своих соседей Трансфер определяет своё поведение (push, pull, subscribe и др.), но никогда не ссылается и не проверяет класс другого трансфера. Он не знает, что является upstream или downstream — лишь выполняет свой контракт. Пользователь может создать свой трансфер, объявить и реализовать его возможности — и он органично и бесшовно впишется в экосистему.
2. Мосты не знают конкретных реализаций Мост инспектирует capability flags, а не имена классов. Нет цепочки instanceof, нет переключения по имени класса. Любой output-трансфер может быть соединен с любым input-трансфером — при условии совместимости их флагов, о чем мы поговорим чуть ниже. Это применимо и к тем узлам, которые еще не существуют и будут созданы пользователем.
3. Значение undefined никогда не распространяется В Transferum undefined означает «нет данных», а не «пустое значение». Оно подавляется на уровне внутренней реализации менеджера подписок — подписчики никогда не уведомляются с undefined. При этом для явных маркеров пустых значений можно использовать null. Мы сознательно пошли на этот компромисс, чтобы избежать runtime-оверхеда и сохранить нативную скорость работы на плотных потоках данных.
Связывание трансферов
Функция linkTransfers(lhs, rhs) соединяет output-трансфер (lhs) с input-трансфером (rhs) с автоматическим выбором стратегии связывания на основе возможностей этих трансферов:
Protocol-oriented design: механизм не спрашивает «какой это класс?» — он выясняет, какие у него есть возможности. Любая пара трансферов с совместимыми возможностями является linkable. Добавление нового класса трансфера требует только объявления его флагов и реализации соответствующих методов — как связать его с другим трансфером, связующий алгоритм разберется сам.
Sync и async в одной экосистеме
Синхронные и асинхронные трансферы сосуществуют и могут быть связаны между собой. linkTransfers() предпочитает sync-связывание, когда это возможно, а async-стратегии применяет только когда sync неприменим. Нет отдельного «асинхронного мира».
Поддержка backpressure
Ряд асинхронных трансферов (AsyncSinkTransfer, AsyncWriteTransfer, AsyncConvertTransfer, AsyncConditionTransfer) поддерживают необязательные поля в конфигурации: maxConcurrency, bufferSize и onBufferOverflow — для ограничения параллельных async-операций, очереди избыточных данных и graceful-обработки переполнения. По умолчанию — неограниченная обработка, без буферизации.
Локальная обработка ошибок
Transferum использует единую модель обработки ошибок для всех трансферов. Каждый трансфер, который может столкнуться с runtime-ошибкой, принимает опциональный onError-хэндлер в своей конфигурации.
А теперь — к примерам использования
Вот так можно просто и декларативно описать опрос и агрегирование данных из нескольких источников.
А вот как можно можно организовать роутинг в игровой механике.
А вот пример сложного цепочечного трансфера, реализующего логику автоматизации обработки событий и принятия решения в торговле на бирже.
Когда имеет смысл попробовать Transferum
Библиотека подойдет для:
TypeScript-first проектов — благодаря максимально строгой типизации и compile-time вычислению доступных методов любого трансфера на основе объявленных у него флагов возможностей.
Работы с pull-based источниками данных — polling API, датчиков, хранилищ с PollingProxy.
Смешанных sync/async пайплайнов — в единой модели без ручного преобразования.
Явного flow control — gates, bridges, selectors для runtime-маршрутизации.
Game development / IoT — frame-aligned tickers, idle polling, sensor aggregation.
Устойчивой обработки ошибок — локальная, non-fatal обработка: одна стадия не убивает пайплайн при условии переданного в конфиге обработчика ошибок, ничего не подавляется молча.
Результаты и планы
Библиотека уже используется в двух наших внутренних проектах и показывает свою эффективность. Код доступен на GitHub под лицензией MIT, библиотека не имеет внешних зависимостей и поставляется с подробной документацией (README + API Reference).
В одном из проектов граф состоит из ~80 узлов и стабильно обрабатывает несколько сотен событий в секунду без деградации. На основе этих данных в том числе рендерится 3D-сцена в Babylon.js со стабильным фреймрейтом ~60 FPS без микрофризов.
Тесты библиотеки покрывают не только отдельные трансферы, но и поведение системы в динамике: переподключение мостов, обработку ошибок в длинных асинхронных цепочках, а также разнообразные граничные случаи. Покрытие — 100%.
В дальнейшем планируем реализовать хуки и утилиты для более удобного и нативного использования Transferum с Vue и React. Если они окажутся в достаточной мере переиспользуемыми, оформим в отдельные пакеты-адаптеры.
Буду рад, если вы заглянете в репозиторий, попробуете библиотеку в деле и поделитесь замечаниями — обратная связь поможет сделать Transferum лучше.
P. S. Если вы сталкивались с похожими задачами и решили их как-то иначе — буду рад прочитать о вашем опыте в комментариях.
Спустя полгода покадровой ручной рисовки, коддинга в Godot, написания музыки и кучи сожженных нервов, я наконец-то выпустил свою первую атмосферную 2D-метроидванию — The Rising Omen. Это мрачный экшен-платформер в стиле фэнтези.
Проект дался очень тяжело. За это время было минимум три жестких момента, когда опускались руки и хотелось полностью всё дропнуть. Делюсь опытом, с какими «главными боссами» разработки я столкнулся:
1) Болото из мусорного кода В самом начале я перепробовал кучу вариантов, чтобы персонаж просто нормально атаковал. С хитбоксами творился полный кошмар — всё работало криво, косо и с багами. В итоге я понял, что код превратился в кашу. Пришлось принять тяжелое решение: удалить вообще всё, вычистить проект и переписать боевую систему абсолютно с нуля. Было обидно терять время, но это научило меня чистоте кода.
2) Месяц на одну функцию (Chase AI) Я убил почти четыре недели только на то, чтобы настроить функцию преследования игрока врагами. Логика постоянно ломалась: противник мог подойти, сделать один удар и просто замереть на месте навсегда. Либо наоборот — намертво вставал и бесконечно спамил анимацию удара, вообще не двигаясь. Настройка плавных переходов между ходьбой, погоней и атакой заняла в разы больше времени, чем я рассчитывал.
3)Финальный босс: Слайд-шоу в движке В какой-то момент игра начала нещадно лагать. Сам Godot просто зависал при попытке зайти на любую сцену, а ФПС упал до 10–15 кадров. Я потратил кучу дней, оптимизируя всё подряд: текстуры, скрипты, физику — ничего не помогало. В полном отчаянии я пошел в сообщество по Godot. И там мне подсказали решение, за что ребятам бесконечная благодарность! Оказалось, дело в одной кнопке: в настройках рендера проекта у меня стоял режим Mobile, а для моего железа нужно было выставить GL Compatibility. Изменение одной настройки мгновенно вернуло плавность.
Пройдя через все эти круги геймдев-ада, я всё-таки довел игру до релиза!
Уже несколько лет я веду D&D, в основном очные игры т.к. для друзей, да и с онлайн-форматом по разным причинам не сложилось.
Как это часто бывает, по ходу дела возникают не то что проблемы, а скорее неудобства и хочется их как-то порешать. Пока начал с двух небольших приложений для мастера-очника.
DndMapHelper
Это программа для проведения путешествий и показа карт игрокам со второго экрана (скажем, телевизора, подключенного к ноуту)
Что умеет:
показывать карту игрокам на отдельном экране или телевизоре;
делить информацию на доступную мастеру (вся) и игрокам (текущий маршрут, выбранные мастером области и т.д.);
строить маршруты и двигать по ним партию;
считать протяженность маршрута, время пути и расход припасов - на случай если вы захотите устроить вашим приключенцам игры на выживание или скажем следить за тем, сколько времени прошло в мире, пока ваши игроки шли из пункта А в пункт Б
создавать области с описаниями: регионы страны, районы города и т.д.
прикреплять цели путешествия, случайные и не очень встречи по пути и квесты к карте;
сохранять всё перечисленное выше в одном файле и загружать из него.
В общем, не слишком сложный и потенциально весьма прикольный инструмент визуализации путешествий и исследований.
NPCNotebook
Вторая программа посвящена NPC. Если у вас много неписей в партии, или ваши игроки внимательные и выясняют, как зовут того стражника на воротах, пьяницу за дальним столом в таверне и прочих уважаемых господ, то запоминать их в какой-то момент становится не просто. Можно конечно завести записную книжку или файлик в блокноте, но тут есть вариант получше.
В приложении можно хранить:
портреты;
описание (расу, возраст, голос);
характер;
краткую биографию;
отношения между персонажами - кто кому сын, друг, заклятый враг или должник;
группы персонажей - это может быть локация (таверна, ратуша), организация (арфисты) или ещё какой-то признак, который вам удобен;
реплики персонажей в разных ситуациях - например, диалог при знакомстве, если согласились помочь, если выдвинули обвинение. Все это на разных вкладках, чтобы не запутаться.
Получается что-то вроде личной базы данных NPC, но заточенной именно под работу мастера во время партии - один глаз в программе, другой в игре.
Теги ставлю связанные с ДнД, хотя строгой привязки к системе нет - можно использовать в практически любой НРИ, где так или иначе возникают похожие ситуации.
Собираем девайс на ESP32: API, датчики, экраны и Home Assistant
Плата ESP32 в корпусе, напечатанном на 3D-принтере
Если вы работаете с крупной кодовой базой или монорепами, скромное контекстное окно Claude Code и жесткие лимиты на использование могут несколько ограничивать. Проблему с «памятью» Claude Code я решил с помощью базы данных Postgres, но необходимость постоянно кликать по крошечной иконке, чтобы проверить остаток квоты, жутко раздражала.
В конце концов мне это надоело, и я решил собрать небольшой настольный экранчик для вывода лимитов. Чтобы больше никаких лишних кликов и консольных команд – бросил взгляд и сразу видишь, сколько осталось. Заодно подумал: почему бы не добавить датчик температуры? Пусть девайс измеряет климат у меня в кабинете, а эти данные я потом проброшу в Home Assistant, чтобы настроить автоматическое включение кондиционера.
Показания датчика DHT22 на OLED-дисплее
Подключение датчика DHT22 к плате ESP32
Схема проще некуда. Понадобится стандартная плата ESP32 (доступный микроконтроллер со встроенными модулями вайфая и блютуза), датчик температуры DHT22, обычный монохромный OLED-дисплей (я взял на чипе SH1106, но подойдет практически любой аналогичный) и тактовая кнопка для переключения экранов. Вот и весь набор.
Я набросал простенький корпус в Blender, запустил 3D-принтер и буквально через пару часов держал готовые детали в руках.
Две платы ESP32
Маркировка классического модуля ESP32 и плата ESP32-S3
Настало время загрузить работой наших ИИ-помощников. Все три агента получили один и тот же промпт:
**Я хочу собрать инфопанель на базе ESP32, выполняющую три задачи:**
1. Отображать остаток квоты поиска/запросов моего тарифного плана Claude. 2. Считывать температуру и влажность с подключенного датчика DHT22 и передавать эти данные в систему Home Assistant. 4. Показывать текущую погоду и температуру за окном в Нью-Дели.
**Используемое железо: плата ESP32 Devkit V1, датчик DHT22, монохромный OLED-дисплей SH1106 (128×64). Также подключена четырехконтактная тактовая кнопка – она должна переключать экраны между этими тремя режимами и обновлять дисплей при нажатии.**
Цель была проста: получить рабочий прототип, выполняющий все три задачи, потратив при этом минимум запросов. С ходу идеальный код не выдал никто – каждому агенту потребовалось несколько уточняющих промптов, но пути к решению они выбрали совершенно разные.
❯ Antigravity
Впечатляющий разбег, но планирование оказалось долгим
Первым в бой ринулся инструмент Antigravity от Google на базе Gemini 3.1 Pro (в режиме максимального усердия – High effort). Он оказался чертовски быстрым, но весьма своеобразным. Получив промпт, модель мигом загуглила, как проверять лимиты Anthropic API, выдала пошаговый план разработки и засыпала меня наводящими вопросами.
Antigravity составляет план реализации в ответ на первый запрос
Предложенный Antigravity план работы
Я запускал все три ИИ‑агента одновременно. Пока Codex и Claude Code корпели над кодом, выдавая первые наброски прошивок для ESP32, Antigravity упрямо требовал утвердить его план действий, отказываясь писать даже строчку кода без моего одобрения. Ответив на все его вопросы, я получил… еще один план!
А вдобавок – категоричное заявление: мол, вытянуть лимиты подписки Claude Pro не получится, так как у Anthropic нет официального API для этой функции. Передавать же температуру в Home Assistant ИИ предложил через встроенный REST API – самый простой способ, если не хочется связываться с ESPHome.
Antigravity пытается разобраться с эндпойнтом API для получения лимитов Claude
Код для инфопанели ESP32, сгенерированный Antigravity
Чтобы сдвинуть дело с мертвой точки, я скормил ассистенту ссылку на GitHub-репозиторий Clawdmeter Германна Бьёргвина – это похожий проект на базе платы Waveshare ESP32-S3-Touch-AMOLED-2.16. Только тогда до модели дошло: можно взять OAuth-токен, созданный утилитой Claude CLI, и отправить его на специальный бета-сервер API для получения лимитов. К слову, на тот момент Antigravity все еще не выдал реального кода. Если вы тоже считаете, что Antigravity пока не дорос до уровня Claude Code и Codex, этот случай лишь укрепит вашу веру.
Изменения, которые Antigravity предлагает внести в план реализации
Стоило мне наконец согласовать третий (и, слава богу, последний) план действий, как ИИ за пару минут накатал проект для PlatformIO. Он разбил код на кучу файлов, вынеся пароль от вайфая и OAuth-токен отдельно от основного исходника. С точки зрения безопасности подход верный, но для девайса, который никогда не выйдет за пределы домашней сети, городить такую архитектуру – явный перебор. Новички в мире Arduino IDE и ESP32 от подобной россыпи файлов вместо одного понятного скетча и вовсе могут впасть в ступор.
Инфопанель ESP32 под управлением кода от Antigravity
❯ Codex так и не понял задачу
Ошибки, которые лишили шансов на успех
Созданный OpenAI ассистент Codex (на базе GPT 5.5 в режиме высокой точности) не стал тратить время на раздумья. Буквально за три минуты он выкатил два YAML-файла, но свернул при этом в совершенно неожиданную сторону. ИИ решил использовать ESPHome, чтобы завязать плату на датчик, изначально совместимый с Home Assistant. Такой подход хорош, если вам нужен чистый термометр в кабинет на базе DHT22. Но когда на плату навешаны еще две совершенно другие задачи, тянуть тяжелую ESPHome – решение сомнительное.
Codex собирает информацию для проектирования инфопанели ESP32
Codex тоже резонно заметил, что у Anthropic нет официального API для проверки лимитов Claude Pro. Но в отличие от Antigravity, это препятствие его ничуть не смутило – он решил обойти его костылями: Codex создал виртуальный ползунок input_number.claude_plan_usage_percent в Home Assistant. Идея в том, чтобы я вручную (или через какую-то внешнюю автоматизацию) двигал этот ползунок, сообщая плате о лимитах! В качестве альтернативы ИИ предложил настроить настоящий сенсор через API, но только если у меня есть админский ключ консоли Anthropic. Которого у меня, конечно же, нет.
Схема подключения компонентов для инфопанели, составленная Codex
В следующем запросе я скинул ему ссылку на тот же репозиторий Clawdmeter. Codex кивнул, мол, идею понял, но вместо того, чтобы отказаться от тяжеловесного ESPHome, упрямо продолжил гнуть свою линию. Он предложил использовать всё те же ручные переменные, добавив, что «следующим шагом будет написание промежуточного моста в духе Clawdmeter, который будет транслировать реальные данные об использовании Claude Code в созданные виртуальные сущности». Зато Codex выдал вполне толковую и наглядную схему подключения компонентов.
Сгенерированный Codex код ESPHome для инфопанели ESP32
Метод, конечно, жизнеспособный, но требующий кучи костылей и неоправданного усложнения на ровном месте. Ощущение, будто Codex зацепился за датчик температуры (наверняка из-за обилия готовых примеров в сети) и попытался втиснуть всю остальную логику в эту экосистему, вместо того чтобы переписать архитектуру под конкретную задачу.
Предложенный Codex код для интеграции в Home Assistant
Codex пытается скорректировать код получения лимитов Claude
Чтобы довести этот прототип до ума, пришлось бы потратить уйму времени на переписки с ИИ. Если честно, мне было бы проще написать всё с нуля самому, чем продираться сквозь дебри ESPHome, куда меня так настойчиво затягивал Codex.
❯ Claude Code не спешил, но сделал всё как надо
Неторопливый итеративный подход, здравая логика и рабочий код
Claude Code, на базе Sonnet 4.6 в режиме High effort, с самого старта оказался медленнее всех. Главным образом из-за того, что серверы были перегружены и утилита то и дело мозолила глаза предупреждением «модель под высокой нагрузкой». Поделать с этим на стороне клиента ничего нельзя, да и столкнулся я с таким впервые за несколько месяцев активного использования Claude Code, так что ругаться не стал.
Ответ Claude на первый запрос по проекту ESP32
Немного подумав, Claude с первой же версии выдал один готовый INO-файл (формат Arduino IDE), выполняющий все три задачи. Никаких капризов, как у Antigravity, или упрямства, как у Codex. Claude Code элегантно решил проблему с лимитами: он просто отправляет POST-запрос /v1/messages со значением max_tokens:1 модели Haiku, получая в заголовках ответа данные о доступных токенах и запросах на текущий период. ИИ четко расписал, какие конкретно лимиты мы сможем увидеть, а какие (вроде общего месячного лимита подписки Claude Pro) вытянуть не удастся.
Claude проверяет эндпойнты API для запроса лимитов
Сообщение Claude об исправлении эндпойнта API
Как и в прошлые разы, я подкинул ссылку на проект Clawdmeter, чтобы упростить задачу. Ассистент сориентировался мгновенно: обновил скетч Arduino новыми заголовками, показал превью будущего экрана и выкатил итоговый понятный INO-файл, полностью готовый для заливки на плату, заботливо приложив инструкцию о том, как получить OAuth-токен.
Схема подключения компонентов от Claude Code
Пояснения Claude к финальной версии кода
Как и Antigravity, Claude настроил передачу данных с термометра через REST API Home Assistant. Однако он подметил важнейшую деталь: если сервер Home Assistant перезагрузится, интеграция «отвалится» до тех пор, пока плата не отправит данные повторно. Чтобы связь не терялась, ассистент порекомендовал использовать протокол MQTT, хотя это и потребует некоторых настроек на стороне умного дома.
Плата ESP32 с прошивкой, сгенерированной в Claude Code
❯ Только один дошел до финиша
Какая модель в итоге выдала рабочий дашборд и почему
Для моих задач идеальным решением оказался именно Claude Code. Он выдал понятную схему подключения деталей и всего один INO-файл, избавив проект от лишней сложности. Для девайса, живущего исключительно внутри локальной домашней сети, плодить файлы ради выноса OAuth-токенов или паролей вайфая попросту бессмысленно.
Готовая инфопанель ESP32
К тому же я давно пользуюсь Claude, так что в его памяти уже хранился мой список датчиков и плат, а также локальный IP-адрес моего сервера Home Assistant. Он просто подставил все это прямо в скетч – мне почти ничего не пришлось править ручками перед прошивкой. Некоторые видят в Claude Code лишь скромного ассистента, но при хорошем контексте он способен заменить целую армию разработчиков.
Впрочем, если вы давно пользуетесь Codex или Antigravity, для вас аналогичной палочкой-выручалочкой могут стать именно они.
Экран уличной погоды на инфопанели ESP32
Экран комнатной температуры всё там же на ESP32
Второе место с небольшим отставанием занял Antigravity. Он изо всех сил пытался сделать всё правильно, но переборщил со сложностью: код пришлось допиливать и отлаживать вручную, прежде чем плата ожила. К тому же Antigravity зажал схему подключения – пришлось выуживать распиновку прямо из исходника, чтобы понять, куда какой проводок втыкать.
Экран лимитов Claude (код сгенерирован Claude Code)
Экран комнатной температуры (код сгенерирован Antigravity)
Наконец, Codex. Идея использовать ESPHome сама по себе неплоха, но лишь в том случае, если бы мы собирали обычный комнатный термометр. Несмотря на мои подсказки по работе с лимитами, ИИ упорно цеплялся за ESPHome, усложняя систему и заставляя меня ковырять YAML, когда для подобной комбопанели гораздо логичнее было накатать обычный код в Arduino. Конечно, можно было заставить агента сменить курс и выдать обычный скетч, как это сделали конкуренты, но это вылилось бы в очередные утомительные циклы переписки, отладки и правки архитектурных косяков.
❯ Выбор инструмента зависит от задачи
Когда важна скорость, когда – точность и в чем предназначение каждого ИИ-ассистента
Как я уже говорил, жизнеспособны все три решения, но некоторые требуют значительной доработки напильником. Нельзя сказать, что какой-то один инструмент безоговорочно лучше остальных; скорее сфера встраиваемых систем наглядно обнажает пропасть между ИИ-инструментами, которые просто генерируют строки кода, и теми, которые действительно вникают в суть инженерной задачи. Результат будет зависеть от ваших привычек и от того, какой путь решения вам ближе.
Antigravity выдает отличную скорость и впечатляет, если скормить ему правильный контекст. Codex как будто бы утыкается в самые популярные и задокументированные методы из интернета, даже когда они вообще не к месту. Но когда дело доходит до проекта, где на скромном и слабом железе нужно подружить несколько разных подсистем, – именно неторопливый, вдумчивый и концептуально более простой подход Claude Code дал единственный результат, который я смог залить на плату и запустить с первой попытки.