Пост tds540

tds540 — приложение jCjS для удалённого опроса регистратора TDS-540 по LAN,
зеркалирования файлов его SD-карты и записи измерений в PostgreSQL.

Текущая версия приложения: v7.

tds540 — пост (приложение) для удалённой работы с регистрирующим устройством
TDS-540 по интерфейсу LAN.

Описание устройства:
TDS-540 — регистрирующее устройство: https://www.tmljp.ru/catalog/izmeritelnaya-elektronika/statika/registriruyushchee-ustroystvo-tds-540/

Каталог приложения относительно корня jCjS:
stuff/nikiet/devs/tds540/
Назначение

Приложение решает основные задачи:

1. контролирует TCP-соединение с TDS-540 по LAN;
2. синхронизирует файлы SD с локальным хранилищем;
3. импортирует новые строки CSV в PostgreSQL;
4. восстанавливает измерения, накопленные во время простоя бэка.
5. продолжает локальное накопление при недоступной SD-карте или БД.

Архитектура

Основные файлы:

- init.js — подключение к PostgreSQL, загрузка каналов и запись CSV;
- tds540.js — LAN-протокол TDS-540, синхронизация SD и обработка файлов;
- init_zip.js — проверенная ZIP-архивация локальных файлов;
- cmd.js — HTTP-команды поста;
- js/cli.js — логика веб-интерфейса;
- index.html, index.tmpl — веб-интерфейс;
- jcjs_tds540.xml — конфигурация приложения.

ПРОШЛАЯ ВЕРСИЯ (v6)

Версия v6 синхронизировала SD-файлы, восстанавливала значения из локальных CSV,
контролировала диапазон каналов и режим измерения, а также принимала
многострочные ответы прибора до END. Работа зависела от доступности SD-карты
и метаданных PostgreSQL при старте.

ТЕКУЩАЯ ВЕРСИЯ (v7)

Прибор автономно измеряет каналы и сохраняет результаты в CSV на SD-карте.
Приложение регулярно выполняет следующую последовательность:

1. LS24 — получает список файлов SD;
2. сравнивает имена и размеры с локальным зеркалом;
3. RD1,<file> — загружает только отсутствующие или изменённые файлы;
4. сохраняет точную копию через временный файл и file.rename();
5. выбирает из CSV строки, которых ещё нет в БД;
6. пакетно записывает измерения в PostgreSQL.

Неизменившиеся файлы повторно с устройства не загружаются.

Перед синхронизацией приложение проверяет внутреннюю память и SD командой
LS21. При отсутствии SD включается резервный прямой опрос; результаты
сохраняются в saveNNN.csv, а пропуск восстанавливается из внутренней памяти
через LS23 и RD0. После возврата SD резервные файлы архивируются, и
приложение автоматически возвращается к файловому режиму.

Очередь команд сохраняется при реконнектах и продолжает работу в ближайшем
безопасном окне. Ошибка стартовой диагностики LS0 или LS21 не блокирует
LS24/RD1-синхронизацию и создание локальных CSV.

Начиная с v5 действует ротация текущего CSV по размеру. Если файл превысил 1 МБ,
приложение сначала сохраняет его полную локальную копию, затем командой FN
переключает прибор на следующий файл dataNNN.csv.

Также действует ротация по количеству файлов: если на SD находится более
150 файлов, после локального копирования удаляются 50 самых старых файлов
измерений; на карте остаётся не менее 100 файлов.

В заголовке веб-интерфейса отображается состояние TCP-соединения с прибором:
(в сети) или красное (нет связи). Индикатор обновляется вместе с
периодическим получением измерений без отдельного HTTP-запроса.

В навигационной панели находится компактная таблица счётчиков TDS-540 и БД.
Она также показывает, завершена ли запись обнаруженных CSV-данных в БД.

Многострочные ответы команд LS и TS принимаются целиком до END.
При старте и в цикле синхронизации команда LS0 проверяет фактические границы
каналов; при расхождении прибор получает диапазон FL<min>,<max> из БД.
Для 420 каналов используется фактическое время сканирования 22 секунды и
защитный запас 5 секунд.

Последние значения, время каналов и режим измерения восстанавливаются из
локальных CSV до подключения к прибору. Поэтому Web сразу после старта готов
показывать накопленные измерения. Текущий режим в таблице статистики доступен
для клика и открывает диалог выбора периода измерения.

SQL-метаданные каналов и сетевой адрес регистратора сохраняются через jcjsObjectSaver.js и
восстанавливаются с диска до подключения к БД. Если БД недоступна, опрос
запускается с диапазоном post.def_chans, а реконнект выполняется раз в 5 минут.

Локальное хранилище

Копия SD находится относительно исполняемого файла jCjS:
../tds540.data/
Каталог является локальным накопителем файлов прибора. В него сохраняются
точные копии загруженных CSV и других файлов SD, а в резервном режиме —
saveNNN.csv с результатами прямого опроса и восстановления внутренней памяти.

При очередной синхронизации приложение сравнивает имя и размер удалённого файла
с локальным. Уже сохранённый неизменившийся файл повторно не загружается.
Изменившийся файл сначала записывается как временный .part, затем
переименовывается в окончательное имя.

Состояние импорта сохраняется через штатный
stuff/include/jcjsObjectSaver.js.
В нём хранятся размер удалённого файла и количество уже обработанных строк.

Архивы создаются относительно исполняемого файла jCjS:
../tds540.arch/
После удаления старого файла с SD его локальная копия помещается в ZIP и только
после проверки архива удаляется из tds540.data. Так локальный каталог сохраняет
тот же набор SD-файлов, что и карта. Резервные saveNNN.csv архивируются после
возврата SD.

Запуск и восстановление после простоя

При старте приложение:

1. восстанавливает метаданные каналов и сетевой адрес регистратора с диска;
2. восстанавливает последние значения и режим из локальных CSV;
3. подключается к PostgreSQL и обновляет метаданные при доступности БД;
4. при недоступной БД использует диапазон post.def_chans;
5. подключается к TDS-540 и определяет состояние накопителей;
6. синхронизирует SD либо включает резервный опрос;
7. импортирует новые CSV-строки при наличии БД.

При успешном восстановлении выводится:
записано в БД: N
Сообщение выводится только при N > 0.

Работа без SD-карты

Команда LS21 контролирует совместную запись во внутреннюю память и на SD.
Если запрос SD завершается ошибкой отсутствия карты, приложение:

1. выполняет SD0 и DM1;
2. получает список внутренней памяти командой LS23;
3. загружает свежие файлы командой RD0 и сохраняет новые строки в
   saveNNN.csv;
4. выполняет прямой ST-опрос с периодом текущего режима;
5. проверяет возврат SD раз в минуту вне измерительного окна.

После возврата карты включается совместная запись SD1, резервные CSV
архивируются в ../tds540.arch, затем возобновляется LS24/RD1-синхронизация.

Режим измерения и период синхронизации

Команда LS22 при старте проверяет состояние интервального измерения.
Протокол возвращает только RUN или STOP, поэтому точный режим определяется
по интервалу временных меток последних строк CSV.

Детектирование режима при синхронизации

При каждой синхронизации приложение последовательно анализирует временные метки
новых строк CSV. Разница между соседними измерениями сопоставляется с режимами:

- интервал около 1 минуты — TS3;
- интервал около 10 минут — TS5;
- интервал около 1 часа — TS7.

При старте анализируются последние последовательные строки локальных CSV,
поэтому режим доступен до первого сетевого обмена. Итоговый режим определяется
по наиболее свежим измерениям и сохраняется между перезапусками приложения.

Во время штатной работы режим проверяется при каждой новой порции CSV. Если
распознанный режим отличается от используемого модулем опроса, обновляются
период синхронизации и сообщение в журнале:

Интервал измерения TS5 (10 минут) установлен на устройстве

 Режим | Интервал измерения | Синхронизация SD | --- | ---: | ---: | TS3 | 1 минута | 3 минуты | TS5 | 10 минут | 10 минут | TS7 | 1 час | 1 час | Если интервальное измерение остановлено или режим не установлен, приложение
устанавливает TS5.

После каждой успешной синхронизации SD приложение выполняет контроль LS22.
При RUN работа продолжается без изменений. При STOP повторно запускается
ранее определённый режим, а если режим неизвестен — TS5.

Следующий запуск синхронизации рассчитывается относительно времени последнего
измерения, а не относительно момента завершения предыдущего опроса.

Управление режимом из Web

Клик по текущему периоду в таблице статистики открывает диалог jQuery UI с
вариантами 1 мин, 10 мин и 1 час. После отправки формы бэк проверяет связь
с прибором и допустимость минутного режима, затем выполняет:

CA → TS0 → FL<min>,<max> → TS3/TS5/TS7

Новый режим отображается и сохраняется только после успешного ответа прибора.
Если измерение впоследствии остановлено, LS22 обнаруживает STOP и запускает
этот же сохранённый режим.

Таймауты и повторное подключение

Расчётное время сканирования:
число каналов × (22000 / 420) мс + 5 секунд
Для 420 каналов это 27 секунд. При таймауте команда учитывается как ошибка,
TCP-соединение закрывается и выполняется повторное подключение.

Одновременно выполняется только одна попытка TCP-подключения. Первая команда
отправляется непосредственно при открытии сокета, а команды, ожидающие
безопасного окна, не удаляются при реконнекте.

Тайм-аут или обрыв стартовой команды LS0 не задерживает синхронизацию:
приложение использует диапазон каналов из БД. Если не отвечает LS21, состояние
SD проверяется прямой командой LS24. LS24 повторяется один раз, после чего
включается резервный прямой опрос с локальной записью.

Если команда TS0, TS3, TS5, TS7 или FL получает ERR-73 во время
сканирования, она повторяется после расчётного времени опроса и дополнительного
защитного интервала 5 секунд. Очередь последующих команд при этом сохраняется.

При завершении приложения команды CA, TS0 или другие управляющие команды
прибору не отправляются. Закрывается только TCP-соединение, поэтому TDS-540
продолжает измерения и запись на SD автономно.

Повторное подключение к недоступной БД выполняется раз в 5 минут; работа с
прибором и локальное накопление CSV в этот период продолжаются.

Ротация SD

Удаление применяется к файлам на SD-карте только после создания локальной
копии. После подтверждения удаления соответствующая локальная копия архивируется.

Логика ротации:

1. команда LS24 получает полный список файлов SD;
2. отсутствующие и изменившиеся файлы ставятся в очередь загрузки;
3. приложение загружает файлы и проверяет создание локальных копий;
4. если текущий CSV превысил 1 МБ, после локального копирования команда FN
   переключает прибор на следующий файл dataNNN.csv;
5. если на SD больше 150 файлов, измерительные файлы CSV/ASC сортируются
   по времени от старых к новым;
6. после завершения копирования старые файлы удаляются командой DE0;
7. удаление выполняется пакетами по 50 файлов;
8. локальные копии удалённых файлов переносятся в проверенный ZIP-архив.

Размер пакета рассчитывается так, чтобы после очистки на SD осталось от 100
до 150 файлов. Например, при 151 файле удаляются 50 старых файлов и остаётся
101 файл. Файл не попадает под очистку до завершения его локального копирования.

Команда смены имени для одного переполненного файла отправляется только один раз.
Факт переключения подтверждается появлением следующего имени при последующем
опросе LS24.

Диагностика

В заголовке таблицы отображается текущее состояние соединения с TDS-540:
(в сети)
(нет связи)
При отсутствии связи текст (нет связи) выводится красным цветом.

В верхней навигационной панели отображается компактная таблица:

 TDS-540 |  |  |  |  |  | База данных |  |  |  | Следующая синхронизация | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 🔌 | ❌ | ✅ | ⏳ | 📤 | 💾 | 🔌 | ❌ | ✅ | 🔗 | время | реконнекты | ошибки | успешно | режим | последняя команда | SD | реконнекты | ошибки | успешно | данные записаны | ЧЧ:ММ:СС | Поле 🔗 показывает ✅, когда все обнаруженные CSV-данные текущего цикла
записаны в БД, и ❌ во время синхронизации или после ошибки импорта.
Ячейка режима интерактивна и открывает диалог его изменения.

Таблица обновляется вместе с данными каналов без дополнительного HTTP-запроса.

Через 30 секунд после запуска, затем раз в 15 минут выводится строка:
[reconn/ok/er]: tds [0/35/2], db [0/22/0]
Поля каждой группы: reconnect/ok/error.

При старте выводится определённый режим:
Интервал измерения TS3 (1 минута)
При обнаружении смены режима выводится:
Интервал измерения TS5 (10 минут) установлен на устройстве
Расширенный диагностический вывод команд, синхронизации SD и прогнозируемого
времени следующего опроса включается при server.logTrsh > 3. Полная
протокольная диагностика очереди, таймаутов и ответов включается при:
server.logTrsh > 4
Changelog

ПРОШЛАЯ ВЕРСИЯ (v6)

Версия v6 добавила целостный приём ответов до END, контроль диапазона каналов,
точный прогноз измерительного окна, восстановление значений из локальных CSV и
управление режимом из Web. Основным источником данных оставалась SD-карта.

ТЕКУЩАЯ ВЕРСИЯ (v7)

Версия v7 продолжает накопление при поломке или извлечении SD: восстанавливает
свежие файлы внутренней памяти, выполняет прямой опрос и пишет saveNNN.csv.
После возврата SD резервные файлы архивируются, а штатная файловая синхронизация
возобновляется автоматически.

Удалённые с SD файлы архивируются в ../tds540.arch; оригиналы из
../tds540.data удаляются только после проверки ZIP. Web показывает фактическое
состояние SD символом 💾.

При отсутствии БД приложение использует диапазон post.def_chans, сохраняет CSV
локально и повторяет подключение раз в 5 минут. SQL-метаданные каналов сохраняются
через jcjsObjectSaver.js и восстанавливаются при старте, поэтому наименования,
ККС и единицы измерения доступны Web до подключения к БД.

Очередь команд теперь сохраняется между реконнектами. Стартовые тайм-ауты
LS0/LS21 не блокируют получение списка SD, а повторная неудача LS24
автоматически включает резервный режим накопления.
