mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(cat): нечисловое поле = индекс 0 ещё в семнадцати командах, ZZGT и ZZBE
Всё найдено новым стендом (test/cat), все правки им же и закрыты.
Нечисловое поле. Правку «TryStrToInt вместо StrToIntDef(s, 0)» однажды получили
пять команд (ZZAU, ZZBP, ZZBM, ZZBS, ZZFI), а остальные остались как были — в
том числе КЕНВУДОВСКИЕ ДВОЙНИКИ тех же самых величин, ходящие в те же сеттеры:
FWxxxx;, SHxx; и SLxx; ставили фильтр 0 (тот же индекс, что чинили у ZZFI),
AG0xxx; и SQ0xxx; — громкость и порог шумоподавителя в ноль, GTxxx; — АРУ в
FAST, PCxxx; и ZZPCxxx; — мощность в ноль. Всего семнадцать команд: CN, FW, GT,
NB, PC, SH/SL, AG, SQ и ZZAG, ZZAR, ZZNA, ZZNB, ZZNR, ZZPC, ZZSQ, ZZST, ZZTB.
Разбор везде приведён к идиоме ZZFL/ZZFH: не число — ошибка формата.
Не тронуты три места, где мягкий разбор безвреден или намеренный: FR сам
сверяет поле с '0'/'1' до преобразования; MD и ZZMD от нечислового получают 0, а
установка идёт от 1, то есть ничего не делают; ZZOS трактует мусор как симплекс
по эталону (default в String2OffsetDirection), и клиенты на это рассчитывают.
ZZGT. Опрос отвечал тремя цифрами (как кенвудовская GT), а установка принимала
ровно один символ: клиент, прочитавший «ZZGT000;» и написавший его назад,
получал «?;» — а читать значение и писать его обратно умеет любой логгер.
Принимаются обе ширины, поле разбирается строго.
ZZBE. Формы были перевёрнуты: опрос «ZZBE;» отвечал «?;», а установка
«ZZBE01;» возвращала данные ('1'), причём саму установку никто не исполнял.
Вся семья «сдвиг VFO на nn шагов» (ZZAD ZZAE ZZAF ZZBF ZZSG ZZSH) — однострочные
заглушки в таблице, и документ числит ZZBE среди нереализованных; приведено к
ним.
ZZEB. Выдача клампится туда же, куда и приём: сетка эквалайзера бывает только
трёх- или десятиполосной. Иначе опрос отдавал число полос, которое разбор той же
команды отвергал.
Стенд: 50 проверок, все зелёные; на коде до этого коммита падают 19.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+30
-4
@@ -176,7 +176,7 @@ CTCSS on/tone, FM repeater dir/offset, FM step, AGC-T, CTUN.
|
||||
| `PR` / `ZZPK` | речевой компрессор вкл/выкл | `CompressorOn` |
|
||||
| `ZZPL` | усиление компрессора, дБ | `CompressorGain` (0..20) |
|
||||
| `ZZET` | кнопка TXEQ | `EQOn` |
|
||||
| `ZZEB` | значения TX-эквалайзера | `EQNumBands` + `EQGains` (формат Thetis, 36 символов) |
|
||||
| `ZZEB` | значения TX-эквалайзера | `EQNumBands` + `EQGains` (формат Thetis, 36 символов). Полос бывает только 3 или 10 — движок (`PushTXEQProfile`) и редактор знают ровно эти два случая, остальное отвергается и не выдаётся |
|
||||
| `ZZTO` | мощность настройки | `TUNLevel` |
|
||||
| `ZZTU` | кнопка TUN | `SetTune` |
|
||||
| `ZZUT` | двухтональник 2TON | `SetTwoTone` |
|
||||
@@ -243,7 +243,7 @@ CW: по CAT прилетает что угодно, а контроллер п
|
||||
функция живёт на самом деле): `ZZAA`, `ZZVG` (громкость — `ZZAG`) · `ZZOA`
|
||||
(антенна RX1) · `ZZAP` (мощность — `ZZPC`) · `ZZDN` (мощность — `ZZPC`; сам
|
||||
`ZZDN` = низ водопада) · `ZZAC` (диапазон — `ZZBS`) · `ZZBI` (фильтр — `ZZFI`)
|
||||
· `ZZMB` (режим — `ZZMD`) · `ZZVA` (обмен VFO — `ZZVS`) · `ZZPD`, `ZZPO`
|
||||
· `ZZMB` (режим — `ZZMD`) · `ZZVA` (обмен VFO — `ZZVS`) · ★`ZZVB` (усиление приёма в VAC; **опрос** копировал VFO A в VFO B, то есть терял сплит оператора, — тело переписали позже комментария) · `ZZPD`, `ZZPO`
|
||||
(мощность и питание — `ZZPC`/`ZZPS`) · `ZZQM` (режим — `ZZMD`) · `ZZSR`
|
||||
(опорный уровень спектра) · `ZZRD`/`ZZRU` (RIT; шаг настройки — `ZZSA`/`ZZSB`).
|
||||
|
||||
@@ -273,8 +273,11 @@ Thetis, у нас есть, ширины полей совпадают с `CATSt
|
||||
| `TCATEngine.Parse` | команды без параметров не проверяли суффикс: `TXanything;` доходил до `CmdTX` и **поднимал передачу**; так же вели себя `RX UP DN BD BU QI RC ID IF`. Эталон отбраковывает лишний суффикс в парсере, по таблице ширин; у нас таблицы нет — список безаргументных команд теперь в `IsParamless` |
|
||||
| `ZZFL` / `ZZFH` | принимали поле любой длины от 4 символов и гнали его через `StrToIntDef`: `ZZFLabcd;` молча схлопывал кромку в ноль. Поле фиксированное — ровно 5 символов со знаком, разбор строгий |
|
||||
| `ZZAU` `ZZBP` `ZZBM` `ZZBS` `ZZFI` | длину поля проверяли, а содержимое — нет: `StrToIntDef(s, 0)` превращал любую нечисловую пару символов в индекс 0. То есть `ZZBSxx;` **переключал диапазон** на нулевой вместо `?;`, `ZZBMxx;` и `ZZAUxx;`/`ZZBPxx;` двигали VFO, а `ZZFIxx;` выбирал фильтр 0. Разбор приведён к идиоме `ZZFL`/`ZZFH`: `TryStrToInt`, иначе ошибка формата |
|
||||
| `CN` `FW` `GT` `NB` `PC` `SH`/`SL` `AG` `SQ`, `ZZAG` `ZZAR` `ZZNA` `ZZNB` `ZZNR` `ZZPC` `ZZSQ` `ZZST` `ZZTB` | ★тот же дефект, найденный сплошным прогоном (`test/cat`): правку получили только пять команд выше, а у остальных `StrToIntDef` остался — в том числе у **кенвудовских двойников уже исправленных величин**. `FWxxxx;`/`SHxx;`/`SLxx;` ставили фильтр 0 (тот же индекс, что `ZZFI`), `AG0xxx;` и `SQ0xxx;` — громкость и порог в ноль, `GTxxx;` — АРУ в FAST, `PCxxx;`/`ZZPCxxx;` — мощность в ноль. Разбор везде строгий. Не тронуты `FR` (сам сверяет `0`/`1`), `MD`/`ZZMD` (нечисловое даёт 0, а установка идёт от 1) и `ZZOS` — там мусор трактуется как симплекс намеренно, по эталону |
|
||||
| `ZZGT` | опрос отвечал тремя цифрами (как кенвудовская `GT`), а установка принимала ровно один символ: клиент, прочитавший `ZZGT000;` и написавший его назад, получал `?;`. Теперь принимаются обе ширины |
|
||||
| `ZZBE` | формы были перевёрнуты: опрос `ZZBE;` отвечал `?;`, а установка `ZZBE01;` возвращала данные (`'1'`). Вся семья «сдвиг VFO на nn шагов» (`ZZAD ZZAE ZZAF ZZBF ZZSG ZZSH`) — однострочные заглушки, `ZZBE` приведён к ним |
|
||||
| `KY` / `ZZKY` | текст не ограничивался; поле у Kenwood фиксированное, 25 символов. Длиннее — `?;`: очередь передачи не должна расти произвольно, иначе один пакет уводит станцию в эфир на неопределённое время |
|
||||
| `CATTcp.SendStr` | один `send` на ответ. TCP не обязан отдать весь буфер за раз — длинный ответ (`IF`, `ZZEB`, список режимов) мог уехать обрезанным, и молча: усечение здесь не ошибка. Теперь дописываем остаток в цикле |
|
||||
| `CATTcp.SendStr` | один `send` на ответ. TCP не обязан отдать весь буфер за раз — длинный ответ (`IF`, `ZZEB`, список режимов) мог уехать обрезанным, и молча: усечение здесь не ошибка. Теперь дописываем остаток в цикле. ★И пишем через `WebUtils.SockSend`, а не голым `fpSend`: в нём `MSG_NOSIGNAL`, без которого запись в закрытый клиентом сокет приходит как `SIGPIPE` и убивает процесс целиком (обработчика сигнала в дереве нет, а цикл дозаписи умножает число попыток) |
|
||||
| `CATSerial` | порт помечался активным ДО `SerOpen`; при отказе он навсегда оставался «работающим» в `ActiveCount` и UI, а причина нигде не оседала. Открытие переехало из потока в `TCATSerialPort.Start` (синхронно), появилось свойство `LastError`, поток теперь только читает, а закрывает владелец в `Stop`. Заодно Andromeda-порт назначается только на реально поднявшийся порт |
|
||||
|
||||
Формат `ZZOT` сверен отдельно: эталон читает 9 цифр как МГц с шестью знаками
|
||||
@@ -331,7 +334,7 @@ Thetis, у нас есть, ширины полей совпадают с `CATSt
|
||||
| Область | Команды (примеры) | Причина |
|
||||
|---|---|---|
|
||||
| **Второй приёмник RX2 / sub-RX** | `ZZAB ZZAS ZZBA ZZBB ZZBT ZZMB ZZOB ZZRS ZZSV ZZSX ZZNC ZZND ZZNF ZZNO ZZNU ZZNW ZZFJ ZZFR ZZFS ZZGU ZZLE ZZLF ZZPB ZZRY ZZXO` | один приёмник |
|
||||
| **VAC / VAC2** | `ZZVC ZZVD ZZVF ZZVI ZZVK ZZVM ZZVO ZZVQ ZZVR ZZVT ZZVU ZZVV ZZVX ZZVY ZZVZ ZZYA ZZYB` | нет виртуального аудиокабеля |
|
||||
| **VAC / VAC2** | `ZZVA ZZVB ZZVC ZZVD ZZVF ZZVI ZZVK ZZVM ZZVO ZZVQ ZZVR ZZVT ZZVU ZZVV ZZVX ZZVY ZZVZ ZZYA ZZYB` | нет виртуального аудиокабеля |
|
||||
| **RTTY / DIGI-офсеты** | `ZZRA ZZRB ZZRH ZZRL` | нет RTTY-движка |
|
||||
| **RIT / XIT** | `RT XT RC`, `ZZRF ZZRT ZZXC ZZXD ZZXF ZZXS ZZXU` | нет тракта смещения приёма (CTUN — не замена) |
|
||||
| **Diversity** | `ZZDB ZZDC ZZDD ZZDE ZZDF ZZDG ZZDH` (но не `ZZDA` — это усреднение спектра) | нет диверсити-приёма |
|
||||
@@ -357,6 +360,26 @@ Thetis, у нас есть, ширины полей совпадают с `CATSt
|
||||
|
||||
---
|
||||
|
||||
## 5.1 Стенд
|
||||
|
||||
`test/cat/run.sh` — сборка и прогон `test/cat/cattest.pas` (железа и движка не
|
||||
требует, команды ходят по подставному радио). Проверяет не список команд, а
|
||||
свойства всего набора, и по кодам ходит перебором `AA`..`ZZ`, поэтому новая
|
||||
команда попадает под проверку сама:
|
||||
|
||||
- **круговой прогон** — ответ на опрос обязан приниматься обратно (так нашлась
|
||||
разница ширин у `ZZGT`);
|
||||
- **мусор в поле** — разбор не падает (сборка с `-Criot`), отвечает одним
|
||||
корректным кадром, а нечисловое поле ничего не перестраивает (так нашлись
|
||||
`FW`/`SH`/`SL`/`AG`/`SQ`/`GT` и десяток `ZZ`-двойников);
|
||||
- **точечные регрессии** — заглушки, которые молча правили радио.
|
||||
|
||||
Подробности — `test/cat/README.md`. После правки любой команды прогон
|
||||
обязателен: он дешёвый (секунды) и ловит ровно тот класс дефектов, которым эта
|
||||
подсистема болеет.
|
||||
|
||||
---
|
||||
|
||||
## 6. Как добавить новую CAT-команду (чек-лист)
|
||||
|
||||
1. **Сверить формат** в `CATStructs.xml` + `CATCommands.cs` (Thetis).
|
||||
@@ -369,3 +392,6 @@ Thetis, у нас есть, ширины полей совпадают с `CATSt
|
||||
5. Если команда `ZZ*` ещё не в диспетчере — добавить ветку `else if ext = '..'`.
|
||||
6. Сборка-проверка: `lazbuild -B --ws=qt6 ewsdr.lpr` (GUI-граф включает CAT;
|
||||
headless-демон `ewsdrd` CAT **не** содержит).
|
||||
7. Прогнать стенд: `test/cat/run.sh`. Новая команда попадёт в круговой прогон и
|
||||
в прогон мусором автоматически — если ширины GET и SET разошлись или поле
|
||||
разбирается через `StrToIntDef`, стенд скажет об этом сразу.
|
||||
|
||||
Reference in New Issue
Block a user