148 lines
12 KiB
Markdown
148 lines
12 KiB
Markdown
# Аппаратные приёмочные тесты контроллера
|
||
|
||
## Назначение
|
||
|
||
Проект `tests/Exchanger.HardwareTests` предназначен для проверки реальной платы через Windows USB-COM сразу после её подключения. Он использует те же `SerialPortHardware`, `ControllerAuthenticator`, AES-ключ, parser и `PeripheryMachineController`, что и приложение, поэтому проверяет production-путь, а не отдельную тестовую реализацию.
|
||
|
||
Аппаратные тесты включены в solution для проверки компиляции, но без `EXCHANGER_BOARD_TESTS=1` пропускаются. Обычный `dotnet test Exchanger.sln` не открывает COM-порт, не включает приёмники оплаты и не запускает хоппер.
|
||
|
||
## Перед запуском
|
||
|
||
1. Подключить и запитать контроллер.
|
||
2. Узнать его COM-порт в диспетчере устройств Windows.
|
||
3. Закрыть Exchanger, терминал производителя и другие программы, которые могут удерживать этот порт.
|
||
4. Освободить лоток хоппера и подготовить тестовые деньги только перед интерактивными группами.
|
||
5. Начинать с группы `Safe`.
|
||
|
||
Все команды ниже выполняются из корня репозитория. Результат каждого запуска сохраняется как TRX в локальном каталоге `artifacts/board-tests/`, который исключён из Git.
|
||
|
||
## Безопасная автоматическая проверка
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Safe
|
||
```
|
||
|
||
Группа `HardwareSafe` проверяет:
|
||
|
||
- открытие порта с профилем 115200 8N1/None;
|
||
- аппаратный RTS-reset и полный startup-handshake `periphery controller ver_<version> → 2000 ms → 07 → CHAL → 08 → RAES → READY!` с production AES-256 ECB/NoPadding и обязательной проверкой proof; `AUTH_PC_OK` и `AUTH_CNT_OK` распознаются как промежуточные кадры, но не заменяют точный `READY!`;
|
||
- переходы `Authenticating → Ready → Disconnected`;
|
||
- ответ `INPUT` на команду `91`;
|
||
- соответствие active-low входу: сигнал на `IN1` (`бит 0`) → `Low`, отсутствие сигнала (`бит 1`) → `Enough`;
|
||
- ответы на `140`, `150`, `160`, `3090` и `99` без вывода сырых кадров в отчёт;
|
||
- три цикла закрытия, повторного открытия и повторной авторизации; число циклов меняется параметром `-ReconnectCycles` от 1 до 20.
|
||
|
||
Привязка кнопок и переходов приложения к `141/142`, `151/152`, `161/162/163`, обязательным
|
||
`ASK:*` и пакетным командам `309N` проверяется обычным набором `Exchanger.Tests` через
|
||
wire-симулятор. Группа Safe намеренно не включает приём денег и мотор.
|
||
|
||
Status-тест намеренно требует хотя бы один ответный не-handshake кадр. Если реальная прошивка не отвечает на команду или формат отличается от документации, тест завершится ошибкой и тем самым зафиксирует несовместимость для корректировки parser/документации.
|
||
|
||
На подключённой плате CP210x/COM3 группа `Safe` исторически пройдена 2026-08-27: 9/9 тестов, включая `INPUT<decimal>`, active-low преобразование `IN1` в типизированный уровень запаса, ответы на status-команды и три повторные авторизации. Эти результаты относятся к прежней прошивке и старым запросам `309?/409?`; актуальный runner использует `3090`, поэтому после подключения обновлённой платы пакет требуется повторить.
|
||
|
||
Повторный прогон 2026-08-31 подтвердил новый startup-контракт: отдельный `Probe` прошёл 1/1,
|
||
а `Safe` — 8/9. Исторически были успешны авторизация, `INPUT`/`IN1`, `140`, `150`, старый запрос состояния хоппера, `99` и три
|
||
reconnect-цикла. Только `160` дважды не получил ответ, поэтому эта проверка остаётся красной до
|
||
уточнения наличия/состояния Вендиста или поведения прошивки. Результаты:
|
||
`artifacts/board-tests/board-probe-20260831-105348.trx` и
|
||
`artifacts/board-tests/board-safe-20260831-104124.trx`.
|
||
|
||
Если плата возвращает `CHAL`/`RAES`, но production-проверка proof не проходит, используйте безопасный
|
||
фиксированный probe. Он не запускает периферию и не пишет сырые handshake-блоки в отчёт: сравнивает
|
||
только семантику proof и короткие SHA-256 fingerprints.
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Probe
|
||
```
|
||
|
||
## Кнопка SERVICE, монетник, купюроприёмник и датчик
|
||
|
||
Эти тесты ждут ручное действие и не запускаются без `-ConfirmInteractive`.
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Interactive `
|
||
-ConfirmInteractive `
|
||
-CoinRubles 10 `
|
||
-BillRubles 100 `
|
||
-StockInput 1 `
|
||
-ExpectedStock Enough `
|
||
-InteractionTimeoutSeconds 90
|
||
```
|
||
|
||
Во время запуска тест попросит:
|
||
|
||
- нажать физическую кнопку `SERVICE`;
|
||
- внести одну монету указанного номинала;
|
||
- внести одну купюру указанного номинала;
|
||
- заранее привести датчик хоппера к ожидаемому состоянию.
|
||
|
||
Для проверки обоих сигналов датчика тест запускается дважды: сначала с `-ExpectedStock Enough`, затем после физического изменения уровня с `-ExpectedStock Low`. По умолчанию используется подтверждённая active-low разводка: сигнал на `IN1` (`бит 0`) → `Low`; альтернативная active-high полярность задаётся как `-StockLowWhenHigh:$true`.
|
||
|
||
Если конкретная периферия ещё не подключена, соответствующий номинал можно не передавать: такой тест будет отмечен пропущенным, остальные продолжат работу.
|
||
|
||
## Реальная банковская операция
|
||
|
||
Тест Вендиста может списать реальные деньги и требует отдельного осознанного подтверждения:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Payment `
|
||
-CardRubles 10 `
|
||
-ConfirmRealPayment `
|
||
-InteractionTimeoutSeconds 120
|
||
```
|
||
|
||
Проверяется команда оплаты, событие `MONEY:CASHLESS:<сумма>`, обязательный `ASK:CASHLESS:<сумма>` и типизированный итог `Approved`. Автоматический возврат денежных средств тест не выполняет.
|
||
|
||
## Физическая выдача жетонов
|
||
|
||
Тест запускает мотор хоппера и требует отдельного подтверждения:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Dispense `
|
||
-DispenseCount 2 `
|
||
-ConfirmDispense `
|
||
-InteractionTimeoutSeconds 60
|
||
```
|
||
|
||
За один тест разрешено от 1 до 10 жетонов. Текущий интерактивный runner физически проверяет первый хоппер командой `309N`; production-runtime дополнительно поддерживает второй канал `409N`, который покрыт программными тестами. Перед аппаратной приёмкой двух хопперов runner нужно запускать отдельными явно подтверждёнными сценариями, чтобы один запуск не включал два двигателя неожиданно.
|
||
|
||
Прошивочный предел одной пакетной команды — 99 жетонов: приложение не отправляет `309100` или `409100`, на которые плата отвечает ошибками групп 30 и 40. Крупные выдачи обоих каналов проверяются программными тестами как последовательность пакетов максимум по 99.
|
||
|
||
Отдельный интерактивный тест прямого мотора пока использует только `301/300` и считает строки `HOPPER1 PULSE=1`. Production-приложение уже поддерживает симметричный пересчёт второго хоппера `401/400 → HOPPER2 PULSE=1`; его физический прогон требует отдельного явного подтверждения владельца.
|
||
|
||
Реальный приёмочный runner сохраняет предел 10 за один запуск, чтобы случайная проверка не опустошила хоппер. Многожетонная логика и суммарный partial-result проверяются детерминированно в симуляторе.
|
||
|
||
## Отключение USB-кабеля
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tests\Exchanger.HardwareTests\run-board-tests.ps1 `
|
||
-Port COM5 `
|
||
-Group Cable `
|
||
-ConfirmCable `
|
||
-InteractionTimeoutSeconds 120
|
||
```
|
||
|
||
После приглашения нужно отключить USB, дождаться сообщения о потере связи и подключить кабель обратно. Тест периодически пытается открыть то же имя COM-порта и требует второй успешный handshake. Если Windows назначит другое имя порта, запуск завершится ошибкой; новый порт следует передать в следующем прогоне.
|
||
|
||
## Границы набора
|
||
|
||
Набор проверяет все интерфейсы, которые сейчас использует Exchanger. Он специально не отправляет:
|
||
|
||
- `00` RESET и команды обновления прошивки;
|
||
- произвольные команды силовых выходов `20/21/22`;
|
||
- команды световых каналов и конфигурации конкретного автомата;
|
||
- автоматический повтор выдачи после обрыва;
|
||
- недокументированные команды возврата платежа.
|
||
|
||
Такие операции требуют отдельной схемы конкретного аппарата и явного решения владельца. Сырые handshake-кадры, AES-данные и полные ответы платы не включаются в NUnit/TRX-отчёты; сохраняются только безопасные категории сообщений и результаты проверок.
|