diff --git a/docs/pos-scale-2026-10-11/REPORT.md b/docs/pos-scale-2026-10-11/REPORT.md index 04260cd..730abd2 100644 --- a/docs/pos-scale-2026-10-11/REPORT.md +++ b/docs/pos-scale-2026-10-11/REPORT.md @@ -88,6 +88,50 @@ Linux-сборку не ломали (System.IO.Ports/System.Management общи тогда уточним смысл флага и control-байта (сейчас они логируются, но не интерпретируются). +## Исправление бага автопоиска (Bluetooth) — по реальному запуску на кассе 11.10 + +**Симптом (sysadmin):** на ноутбуке магазина порты COM7/COM8 (Bluetooth, «The write +timed out»), COM15–17 (неопознанные), **COM22 = USB-SERIAL CH340 (там весы)**. +«Найти весы» → «Весы не найдены ни на одном порту», хотя ручной выбор +COM22/57600/Масса-К-кадр даёт «0,000 кг, стабильно». Причина: автопоиск спотыкался +о Bluetooth-порты (Open/Write на них висят) и до COM22 не доходил; по умолчанию в +списке стоял COM7 (Bluetooth). + +**Исправлено (и в кассе, и в HwCheck):** +- Порты классифицируются по типу (WMI, без открытия): **USB-serial** (CH340/ + Prolific/FTDI/CP210x), **Bluetooth** (BTHENUM/«по соединению Bluetooth»), + неопознанные. Порядок автопоиска: **USB-serial → неопознанные → Bluetooth**. +- На каждый порт — **жёсткий таймаут** (Open обёрнут в задачу с гонкой против + Task.Delay; при зависании транспорт принудительно закрывается). Порты + перебираются **параллельно (до 4)**, общий бюджет ~15 с. Любая ошибка/таймаут + на порту → следующий порт, перебор не останавливается. +- **Лог по каждому порту** в окне: «COM22 (USB-SERIAL CH340): ENQ→ACK, вес 0.000 кг», + «COM7: пропущен Bluetooth-порт», «COM15: нет ответа». Листинг портов тоже не + открывает Bluetooth (помечает «не опрашивается»). По умолчанию выбирается + НЕ Bluetooth-порт. +- Из zip hardware-check **убран ярлык «(с тестовой печатью).bat»** (печать — только + отдельно, по слову владельца). +- Юнит-тесты: «зависающий» порт (Open 30 с) **не задерживает поиск дольше таймаута**, + живой порт вторым — **найден**; USB-serial проверяется раньше Bluetooth + (BT не трогаем). Всего по оборудованию 53/53 зелёных. + +**Проверка на Windows 11 (VM):** «Проверка оборудования» запущена с автопоиском +(`--autofind`) — перебрала COM1, записала в журнал «COM1: нет ответа» и **завершилась +быстро, без зависания** (на VM нет весов и нет Bluetooth-порта). См. +`vm-hwcheck-autofind.png`. + +**НОВЫЙ zip hardware-check (с фиксом):** +`~/pos-release/allmarket-pos-win-x64-20261011-0906-hardware-check.zip` +SHA256 `ac5cedef0f5dd63e98f0f3044ef453666f71d8c18280107983b1023cbd573623` +(один ярлык «Проверка оборудования.bat», без ярлыка печати). + +**Полная проверка с эмулятором весов + «зависающим» виртуальным портом (п. 7) — +по-прежнему требует com0com на VM**, установка драйвера которого упирается в доверие +издателю (см. выше) — ждёт решения владельца. Поведение «не виснуть на зависшем +порту» доказано юнит-тестом детерминированно; на VM показано, что автопоиск логирует +по портам и быстро завершается. + ## Файлы - `vm-hwcheck-launch.png` — окно «Проверка оборудования» на Windows 11. -- `index.html` — та же сводка со скриншотом. +- `vm-hwcheck-autofind.png` — автопоиск с журналом по портам (COM1), без зависания. +- `index.html` — сводка со скриншотами. diff --git a/docs/pos-scale-2026-10-11/index.html b/docs/pos-scale-2026-10-11/index.html index 002768b..5aafeb0 100644 --- a/docs/pos-scale-2026-10-11/index.html +++ b/docs/pos-scale-2026-10-11/index.html @@ -17,6 +17,8 @@ code{background:#eef2f7;padding:1px 5px;border-radius:4px;font-size:13px}
  • ✓ Контрольная цифра EAN-13/EAN-8; сканер vs ручной ввод
  • ✓ Юнит-тесты оборудования: 50/50 зелёных
  • ✓ «Проверка оборудования» запускается на реальной Windows 11 (скриншот ниже)
  • +
  • ✓ Фикс автопоиска: USB-serial первыми, Bluetooth последними, жёсткий таймаут на порт, параллельно, лог по портам (баг на кассе 11.10 — виснул на Bluetooth, не доходил до CH340)
  • +
  • ✓ Тест: «зависающий» порт (Open 30 с) не задерживает поиск; живой порт вторым — найден
  • ✗ Живое чтение веса через виртуальную пару COM на VM — НЕ выполнено (драйвер com0com требует доверия издателю; нужно решение владельца)
  • ✗ Реальные весы с грузом (гирей) в магазине — НЕ проверялись (нужен человек)
  • @@ -26,5 +28,9 @@ code{background:#eef2f7;padding:1px 5px;border-radius:4px;font-size:13px}
    «ALL MARKET — Проверка оборудования» на Win11 (VM): без входа; определены COM1 и принтер; тестовая печать выключена; поле сканера активно.
    +
    +
    Фикс автопоиска на Win11: перебрал COM1, записал в журнал «COM1: нет ответа», завершился быстро без зависания (на VM нет весов/Bluetooth).
    + +

    Подробности, SHA256 сборок и список «нужно решение владельца» — в REPORT.md.

    diff --git a/docs/pos-scale-2026-10-11/vm-hwcheck-autofind.png b/docs/pos-scale-2026-10-11/vm-hwcheck-autofind.png new file mode 100644 index 0000000..8e5db16 Binary files /dev/null and b/docs/pos-scale-2026-10-11/vm-hwcheck-autofind.png differ diff --git a/src/food-market.pos.hwcheck/MainWindow.cs b/src/food-market.pos.hwcheck/MainWindow.cs index 83f0b4d..68a1055 100644 --- a/src/food-market.pos.hwcheck/MainWindow.cs +++ b/src/food-market.pos.hwcheck/MainWindow.cs @@ -66,6 +66,9 @@ public MainWindow(bool allowTestPrint) _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(350) }; _timer.Tick += (_, _) => LiveTick(); + + if (Program.AutoFind) + Dispatcher.UIThread.Post(() => DiscoverScale(), DispatcherPriority.Background); } private Control BuildLayout() diff --git a/src/food-market.pos.hwcheck/Program.cs b/src/food-market.pos.hwcheck/Program.cs index 41a9554..6f041c7 100644 --- a/src/food-market.pos.hwcheck/Program.cs +++ b/src/food-market.pos.hwcheck/Program.cs @@ -8,15 +8,42 @@ internal static class Program /// (ключ даёт владелец). Без него кнопка «Тестовая печать» выключена и на принтер /// ничего не отправляется. public static bool AllowTestPrint { get; private set; } + /// Запустить автопоиск весов сразу при открытии (для скриншотов/проверки). + public static bool AutoFind { get; private set; } [STAThread] public static int Main(string[] args) { AllowTestPrint = args.Contains("--allow-test-print"); + AutoFind = args.Contains("--autofind"); + // Headless-режим для скриптов/интеграционного теста: одно чтение веса и выход. + // --read-once [BAUD] [MassaKFrame|MassaKAscii|Cas] + if (args.Contains("--read-once")) return ReadOnceCli(args); BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); return 0; } + private static int ReadOnceCli(string[] args) + { + int i = Array.IndexOf(args, "--read-once"); + string port = (i + 1 < args.Length) ? args[i + 1] : ""; + int baud = (i + 2 < args.Length && int.TryParse(args[i + 2], out var b)) ? b : 57600; + var proto = (i + 3 < args.Length && Enum.TryParse(args[i + 3], out var p)) + ? p : Core.Hardware.ScaleProto.MassaKFrame; + if (string.IsNullOrEmpty(port)) { Console.Error.WriteLine("usage: --read-once [BAUD] [PROTO]"); return 2; } + try + { + using var t = new Core.Hardware.SystemSerialTransport(port, baud); + t.Open(); + var (r, hex, err) = Core.Hardware.SerialScaleReader.ReadDetailed(t, proto); + if (r is null) { Console.Error.WriteLine($"FAIL: {err} hex=[{hex}]"); return 1; } + Console.WriteLine($"OK kg={r.Value.Kg:0.000} unit={r.Value.Unit} flag='{r.Value.Flag}' " + + $"control={(r.Value.Control is null ? "-" : "0x" + r.Value.Control.Value.ToString("X2"))} hex=[{r.Value.RawHex}]"); + return 0; + } + catch (Exception ex) { Console.Error.WriteLine("ERR: " + ex.Message); return 3; } + } + public static AppBuilder BuildAvaloniaApp() { var b = AppBuilder.Configure().UsePlatformDetect();