Files
cuframes-composer/include/cuframes_composer/cpp/temp_overlay.hpp
T
gx 362871a264 Phase 11b: глобальный temperature overlay (правый-нижний угол)
User: "в предыдущих версиях у нас показывалась температура, можешь
сделать в нижнем правом углу оверлей не привязанный к сеткам?". Восстановили
прежнее поведение из vf-cuda-grid/controller (dynamic_overlays.py).

Новый класс cfc::TempMqttOverlay:
  - libmosquitto subscriber в отдельном thread'е, auto-reconnect 1→30s
  - json-c для parse JSON payload — extract поле .temperature (double)
  - Формат: "%+.1f°C" (например "+18.5°C")
  - Persistent FreeType text overlay (cfc_overlay_create_text), kept в
    Composer::overlays_[] backward-compat листе — рендерится поверх Layout
  - reposition_overlay() — пересчёт x/y после text_size() (right-bottom anchor)

C-shim (composer_c_api.cpp) для grid_record.c:
  - cfc_temp_overlay_start(composer, host, port, user, pw, topic, W, H)
  - singleton (один temp overlay на процесс, прода-композитору хватит)

CLI: --temp-topic="zigbee2mqtt/Температура на улице". MQTT credentials
переиспользуются из --mqtt-host/--mqtt-user/--mqtt-pass.

Compose override (localhost-infra):
  --temp-topic=zigbee2mqtt/Температура на улице

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 09:58:47 +01:00

91 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* TempMqttOverlay — глобальный overlay температуры (Phase 11b).
*
* Не привязан к сеткам/cells: рендерится в фиксированной позиции на output
* frame'е, поверх любого layout'а. Подписывается на MQTT topic, парсит JSON
* payload (поле "temperature"), форматирует "+18.5°C", обновляет persistent
* text overlay.
*
* Реализация:
* - libmosquitto subscriber в собственном thread'е (loop_start, auto-reconnect)
* - json-c для parse JSON payload
* - cfc_overlay_t (overlay.c, FreeType atlas) для рендера
* - text update через cfc_overlay_update_text — rebuild atlas при смене строки
*
* Совместима с прошлой реализацией:
* topic = "zigbee2mqtt/Температура на улице"
* format = "+18.5°C" (signed, 1 decimal)
*
* Лицензия: LGPL-2.1+
*/
#ifndef CUFRAMES_COMPOSER_CPP_TEMP_OVERLAY_HPP
#define CUFRAMES_COMPOSER_CPP_TEMP_OVERLAY_HPP
#include "../overlay.h"
#include <atomic>
#include <string>
#include <thread>
/* Forward declarations — namespace глобальный (libmosquitto на C). */
struct mosquitto;
struct mosquitto_message;
namespace cfc {
struct TempOverlayConfig {
std::string host = "cctv-mosquitto";
int port = 1883;
std::string username;
std::string password;
std::string topic = "zigbee2mqtt/Температура на улице";
/* Anchor — позиция overlay'я. Координаты пересчитываются после первого
* получения текста (нужно знать ширину atlas'а). */
int frame_w = 1920;
int frame_h = 1080;
int margin_right = 32;
int margin_bottom = 24;
int pixel_size = 32;
std::string font_path = "/fonts/DejaVuSans-Bold.ttf";
int r = 255, g = 255, b = 255;
int alpha = 230;
/* Префикс перед температурой (например "Улица: "). Пусто — только число. */
std::string label_prefix;
};
class TempMqttOverlay {
public:
explicit TempMqttOverlay(const TempOverlayConfig& cfg);
~TempMqttOverlay();
TempMqttOverlay(const TempMqttOverlay&) = delete;
TempMqttOverlay& operator=(const TempMqttOverlay&) = delete;
/* Запустить subscriber thread + создать overlay. После start() overlay
* добавляется в композитор через add_overlay(). */
bool start();
/* Опаковый pointer на overlay — Composer хранит в overlays_[] для draw. */
cfc_overlay_t* overlay() const { return overlay_; }
private:
static void on_connect(struct mosquitto* m, void* user, int rc);
static void on_message(struct mosquitto* m, void* user, const struct mosquitto_message* msg);
void handle_payload(const char* payload, std::size_t len);
void update_text(const std::string& text);
void reposition_overlay();
TempOverlayConfig cfg_;
struct mosquitto* mosq_ = nullptr;
cfc_overlay_t* overlay_ = nullptr;
std::atomic<bool> running_{false};
std::string last_text_; /* кеш для idempotent update */
};
} // namespace cfc
#endif /* CUFRAMES_COMPOSER_CPP_TEMP_OVERLAY_HPP */