# RB-Modem: GPIO-счётчик импульсов → MQTT

Пять вариантов одного и того же скрипта (счётчик на io3 → публикация в
MQTT) — для сравнения архитектурных подходов на Lua.

## Файлы

| Файл | Вариант | Подход |
|---|---|---|
| `v1_single_loop.lua` | v1 | один поток, линейный main-loop |
| `v2_coroutines.lua` | v2 | один поток, 4 корутины (counter/mqtt-watch/modem/heartbeat) через свой scheduler |
| `v3_oop.lua` | v3 | один поток, 3 класса (`PulseCounter`, `MqttLink`, `ModemLink`) через метатаблицы |
| `v4_01_modem.lua`, `v4_02_counter.lua`, `v4_03_mqtt.lua` | v4 | 3 независимых потока, связь через zbus (`app_modem_event_subscriber`, `app_mqtt_tx_chan`) |
| `v5_library.lua` + `v5_main_driver.lua` | v5 | библиотека-модуль (`M`) + отдельный драйвер, который её `require`-ит и дёргает `tick()` |

**Деплой на устройство:**
- v1/v2/v3 и `v5_main_driver.lua` — как единственный `/scripts/main.lua`;
- `v5_library.lua` — отдельно, в `/libs/v5_library.lua` (имя файла должно
  совпадать со строкой в `require("v5_library")`, `require` ищет модули
  только в `/libs`);
- v4 — три файла как `/scripts/01_modem.lua`, `/scripts/02_counter.lua`,
  `/scripts/03_mqtt.lua`.

## За счёт импульсов отвечает

Считает цепь **`io3`** в режиме `MODE_SW_COUNTER` (программный счётчик по
прерыванию с антидребезгом `deb_us=50000`) — задано константой
`COUNTER_CHAIN`/`cfg.chain` в каждом варианте. Счёт умеют только цепи
`io1`/`io2`/`io3`/`1wire` (`out` — только выход, счётчиком быть не может).
Для аппаратного PCNT-счётчика переключить `COUNTER_MODE`/`cfg.mode` на
`"hw"` — тогда доступны те же `io1`/`io2`/`io3`/`1wire`.

Тестовый импульс без внешней кнопки: соединить `io3` с `out` и дёргать
`out` через shell (`app_gpio set out 0` / `1`, пауза ≥100 мс).

## MQTT для просмотра данных

- Брокер: `test.mosquitto.org:1883`, без TLS и аутентификации.
- Топик: `rb_modem/<chip_id>/pulse/io3/state`
  (подписка на все устройства сразу: `rb_modem/+/pulse/#`)
- Payload:
  ```json
  {"device":"<chip_id>","chain":"io3","count":123,"delta":5,"timestamp":1720123456}
  ```
- QoS 1, retain false. `<chip_id>` берётся из `app_sysinfo.id()`.
- v2 дополнительно раз в 30 с шлёт heartbeat на
  `rb_modem/<chip_id>/pulse/heartbeat` (QoS 0).
