362871a264
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>
91 lines
3.3 KiB
C++
91 lines
3.3 KiB
C++
/* 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 */
|