poe-svelte-ui-lib 1.79.0 → 1.79.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -61,7 +61,7 @@ npm install poe-svelte-ui-lib
61
61
 
62
62
  **Битовые поля конфигурации** — `bitFieldGet(word, start, end)`/`bitFieldSet(word, start, end, value)`: поле `start..end` 32-битного слова `{GROUP}.Cfg` (Select/Input с `bitMode`) обычной арифметикой, без знаковых 32-битных операций JS — бит 31 разбирается и собирается корректно, результат всегда 0..2³²−1; тест против эталона на BigInt — `tests/bitField.test.mjs`.
63
63
 
64
- **Ядро протоколов** — `poe-svelte-ui-lib/protocols`, описание протокола — [`src/lib/protocols/PROTOCOL.md`](src/lib/protocols/PROTOCOL.md) (без Svelte, работает и под Node без Vite): общий для DevCloud, WebApp и SYP-DevTerminal CBOR-кодек (RFC 8949); `valueToCbor`/`cborToValue` — обычные значения, двоичные данные как `Uint8Array` (WebSocket, хранилище, телеметрия); `jsonToCbor` — JSON-совместимое значение в CBOR, строки base64 под ключами с `BIN` — байты (поля ввода терминала и отладки). Пакет `poe_cbor_pkt` — indefinite-массив объектов `[[TrgBusID, SrcBusID, HAR, Payload, CRC16], …]` (CAN, RS485, UART-консоль), `Payload` — одно CBOR item (сырые данные — `encodePacketBytesPayload`, пустой массив — `null`): `encodePacket`/`decodePacket` (разбор с начала буфера — `complete` с длиной, `incomplete` для потока или `garbage`; объекты одному адресату не склеиваются, порядок сохраняется, неверный CRC — флаг `crcOk`), `BUS_ID_REGEXP`/`parseBusId`/`formatBusId` — поля BusID в HEX и вывод `0x0000`, `makeHar(header, argument, reply = true)`/`splitHar` — `HAR`: заголовок в битах 14-15, аргумент в битах 1-13 (0..8191), флаг ответа в бите 0 (как `HAR`/`HAR_NR` прошивки), `packetObjectCrc`; контрольная сумма `crc16Kermit` — строго побайтная, как в `common.c` прошивок. Байты совпадают с `poe_cbor_pkt.c` прошивки — проверка `npm run TestProtocols` (`tests/protocols.test.mjs`, эталонные пакеты собраны прошивочным кодом). Протокол xPOE-Debug (UART-консоль `system_console`) — тот же пакет `poe_cbor_pkt` вперемешку с текстом загрузчика: `encodeXPoeDebugFrame(header, argument, payload, srcId, trgId, reply)` кодирует запрос, `xPoeDebugHar` — HAR по именам словаря, `createXPoeDebugParser().push(байты)` разбирает поток пакетов (каждая запись — отдельный элемент) и внешний текст (`raw`), логи `OK! DebugLog` — `[уровень, тег, текст, FHS]` (`DEBUG_LOG_ARGUMENT`, FHS — в `freeHeap`). Строка таблицы — `xPoeDebugRow`, колонки — `xPoeDebugTableColumns` (основной вход библиотеки): общие для отладки облака и терминала. Ячейка Value — `formatXPoeDebugValue` (CBOR одной строкой, `DebugLog` — уровень · тег · текст), окно по клику — `formatXPoeDebugModal`: Value в развёрнутом виде (`formatXPoeDebugPretty` — то же чистым текстом; карты и массивы с отступами, `DebugLog` — уровень и тег, ниже текст или дамп и FHS) в цветах палитры темы — ключи `--pink-color`, строки `--purple-color`, числа `--red-color`, логические `--orange-color`, `null` — `--cyan-color`, байты `--green-color`, HEX — байты `Payload` по 16 в строке; числа float32 выводятся кратчайшей записью (`0.12`). CAN/CAN FD через slcan-адаптер (`can_service` прошивки): `canFragments`/`encodeCanPacket` — нарезка пакета на кадры как `CAN_Send` (бит 10 ID — «последний», биты 0..9 — `packetId`, по 8 / 64 байта), `encodeSlcanFrame`, `createCanParser().push(байты)` — разбор кадров slcan со сборкой фрагментов и обрезкой паддинга CAN FD. RS485 — сырой поток пакетов: `createPacketStreamParser().push(байты)` (пауза обрывает недособранное, мусор пропускается по байту). Открытие slcan-адаптера — `slcanOpenCommands(скорость, скоростьДанных?)`. Поле Value команды xPOE-Debug из ввода — `xPoeDebugValueFromText` (hex как есть, JSON → CBOR, пусто — пустой Payload). Графики отладки — пакет `OK! DebugPlot` (`LOG_PLOT` прошивки, `DEBUG_PLOT_ARGUMENT`): `debugPlotValues(value)` — пары `[имя, число]` из HEX CBOR-карты `Payload`, `createPlotGroups().update(пары)` раскладывает по группам (префикс до точки) в порядке карты и возвращает обновлённые группы, `data(группа)` — последние значения. Словарь протокола — `HEADER_CODES`, `DEFAULT_ARGUMENT_CODES` (генерируется из мастер-словаря `src/lib/protocols/dictionary.yaml` — `npm run Dictionary`, перед упаковкой автоматически; сам файл поставляется как `poe-svelte-ui-lib/protocols/dictionary.yaml`, `.framework/Dictionary.yaml` прошивок — его справочные копии, сборка прошивок сверяет с ними `api_har.h`), `parseArgumentDictionary` (строки `- [Строка, Enum, Число]`), `nameByCode`. Своих копий протоколов и словаря в приложениях не держим: терминал и отладка облака читают и пишут порт сырыми байтами, разбор и сборка — здесь.
64
+ **Ядро протоколов** — `poe-svelte-ui-lib/protocols`, описание протокола — [`src/lib/protocols/PROTOCOL.md`](src/lib/protocols/PROTOCOL.md) (без Svelte, работает и под Node без Vite): общий для DevCloud, WebApp и SYP-DevTerminal CBOR-кодек (RFC 8949); `valueToCbor`/`cborToValue` — обычные значения, двоичные данные как `Uint8Array` (WebSocket, хранилище, телеметрия); `jsonToCbor` — JSON-совместимое значение в CBOR, строки base64 под ключами с `BIN` — байты (поля ввода терминала и отладки). Пакет `poe_cbor_pkt` — indefinite-массив объектов `[[TrgBusID, SrcBusID, HAR, Payload, CRC16], …]` (CAN, RS485, UART-консоль), `Payload` — одно CBOR item (сырые данные — `encodePacketBytesPayload`, пустой массив — `null`): `encodePacket`/`decodePacket` (разбор с начала буфера — `complete` с длиной, `incomplete` для потока или `garbage`; объекты одному адресату не склеиваются, порядок сохраняется, неверный CRC — флаг `crcOk`), `BUS_ID_REGEXP`/`parseBusId`/`formatBusId` — поля BusID в HEX и вывод `0x0000`, `makeHar(header, argument, reply = true)`/`splitHar` — `HAR`: заголовок в битах 14-15, аргумент в битах 1-13 (0..8191), флаг ответа в бите 0 (как `HAR`/`HAR_NR` прошивки), `packetObjectCrc`; контрольная сумма `crc16Kermit` — строго побайтная, как в `common.c` прошивок. Байты совпадают с `poe_cbor_pkt.c` прошивки — проверка `npm run TestProtocols` (`tests/protocols.test.mjs`, эталонные пакеты собраны прошивочным кодом). Протокол xPOE-Debug (UART-консоль `system_console`) — тот же пакет `poe_cbor_pkt` вперемешку с текстом загрузчика: `encodeXPoeDebugFrame(header, argument, payload, srcId, trgId, reply)` кодирует запрос, `xPoeDebugHar` — HAR по именам словаря, `createXPoeDebugParser().push(байты)` разбирает поток пакетов (каждая запись — отдельный элемент) и внешний текст (`raw`), логи `OK! DebugLog` — `[уровень, тег, текст, FHS]` (`DEBUG_LOG_ARGUMENT`, FHS — в `freeHeap`). Строка таблицы — `xPoeDebugRow`, колонки — `xPoeDebugTableColumns` (основной вход библиотеки): общие для отладки облака и терминала. Ячейка Value — `formatXPoeDebugValue` (CBOR одной строкой, `DebugLog` — уровень · тег · текст), окно по клику — `formatXPoeDebugModal`: Value в развёрнутом виде (`formatXPoeDebugPretty` — то же чистым текстом; карты и массивы с отступами, `DebugLog` — уровень и тег, ниже текст или дамп и FHS) в цветах палитры темы — ключи `--pink-color`, строки `--purple-color`, числа `--red-color`, логические `--orange-color`, `null` — `--cyan-color`, байты `--green-color`, HEX — исходные байты `Payload` сплошной строкой; числа float32 выводятся кратчайшей записью (`0.12`). CAN/CAN FD через slcan-адаптер (`can_service` прошивки): `canFragments`/`encodeCanPacket` — нарезка пакета на кадры как `CAN_Send` (бит 10 ID — «последний», биты 0..9 — `packetId`, по 8 / 64 байта), `encodeSlcanFrame`, `createCanParser().push(байты)` — разбор кадров slcan со сборкой фрагментов и обрезкой паддинга CAN FD. RS485 — сырой поток пакетов: `createPacketStreamParser().push(байты)` (пауза обрывает недособранное, мусор пропускается по байту). Открытие slcan-адаптера — `slcanOpenCommands(скорость, скоростьДанных?)`. Поле Value команды xPOE-Debug из ввода — `xPoeDebugValueFromText` (hex как есть, JSON → CBOR, пусто — пустой Payload). Графики отладки — пакет `OK! DebugPlot` (`LOG_PLOT` прошивки, `DEBUG_PLOT_ARGUMENT`): `debugPlotValues(value)` — пары `[имя, число]` из HEX CBOR-карты `Payload`, `createPlotGroups().update(пары)` раскладывает по группам (префикс до точки) в порядке карты и возвращает обновлённые группы, `data(группа)` — последние значения. Словарь протокола — `HEADER_CODES`, `DEFAULT_ARGUMENT_CODES` (генерируется из мастер-словаря `src/lib/protocols/dictionary.yaml` — `npm run Dictionary`, перед упаковкой автоматически; сам файл поставляется как `poe-svelte-ui-lib/protocols/dictionary.yaml`, `.framework/Dictionary.yaml` прошивок — его справочные копии, сборка прошивок сверяет с ними `api_har.h`), `parseArgumentDictionary` (строки `- [Строка, Enum, Число]`), `nameByCode`. Своих копий протоколов и словаря в приложениях не держим: терминал и отладка облака читают и пишут порт сырыми байтами, разбор и сборка — здесь.
65
65
 
66
66
  **Шапка смарт-виджета** (`WidgetHeader`): значок, заголовок и сворачивание слева, «?» в правом краю; правая часть (режимы, «Обновить» и т. п.) стоит в той же строке, а если не помещается — уходит второй строкой под заголовок и там переносится.
67
67
 
@@ -69,13 +69,13 @@
69
69
  - **Строка состояния** — группы «Система» (ARMED/DISARMED, режим по типу аппарата, индикатор «НАВ» по дисперсии EKF и неисправным датчикам), «GPS» (фиксация, спутники, HDOP), «Связь» (сигнал своей/удалённой стороны, потери пакетов), «Батарея» (В, А, %).
70
70
  - **Авиагоризонт** — небо и земля по крену и тангажу, лестница тангажа через 5°, дуга крена (10/20/30/45/60°), символ самолёта. Ориентация сглаживается между пакетами (Tween 120 мс).
71
71
  - **Лента скорости** (слева, путевая над землёй) и **лента высоты** (справа, над точкой взлёта) с вариометром у края, **лента курса** (снизу): розовый ▲ — трек (куда аппарат реально движется, по `Vx`/`Vy`), зелёный ● — направление на точку взлёта.
72
- - **Углы под лентами** — воздушная скорость (относительно воздуха, отличается от путевой на ветер) и вертикальная скорость (+ набор зелёным, − снижение оранжевым).
72
+ - **Углы под лентами** — воздушная скорость `AS m/s` (относительно воздуха, отличается от путевой на ветер) и вертикальная скорость `VS m/s` (+ набор зелёным, − снижение оранжевым).
73
73
  - **Подсказки** — наведите курсор на любой элемент прибора, строки состояния или значений: расшифровка появляется в информационной строке внизу горизонта: первая строка — величина, единица и текущее значение (обновляется, пока курсор стоит на месте), ниже по строке — что означают знаки, цвета и пороги. Элемент помечен `data-tip` с ключом, тексты собраны в `tips` в скрипте виджета, поэтому её не обрезают края и прокрутка. Без наведения в той же строке — последнее сообщение автопилота (10 с), наведение на неё показывает историю. Включаются и выключаются кнопкой «?» в шапке; выбор общий для всех PFD в браузере (`hintsSetting("WidgetPFD")` из `hints.ts`, ключ `localStorage` `WidgetHints.WidgetPFD`, по умолчанию выключены; прежний выбор `WidgetPFD.tips` переносится).
74
74
  - **Под прибором** — группы «Маршрут» (точка, расстояние, боковое отклонение), «Дом» (расстояние и направление), «Трек», «Позиция» (координаты, MSL), «Воздух» (давление, температура); каждая величина показана один раз.
75
75
  - **Метки целей** (бирюзовые) — целевая скорость и высота текущей точки на лентах, курс на точку ◆ на ленте курса; цель за пределами ленты прижимается к краю.
76
76
  - **Сообщения автопилота** (`STATUSTEXT`) — в информационной строке внизу горизонта на 10 с, цвет по важности; история последних пяти — при наведении на строку.
77
77
  - **Нет данных** — если пакеты не приходили дольше `limits.staleMs` (по умолчанию 2 с), прибор перечёркивается и помечается «NO DATA»; в шапке всегда виден возраст данных.
78
- - **Узкая ячейка** (уже 440 px) — ленты скорости и высоты заменяются числами поверх горизонта.
78
+ - **Узкая ячейка** (уже 440 px) — ленты скорости и высоты заменяются числами поверх горизонта: путевая скорость, м/с, и высота, м, с вертикальной скоростью, м/с.
79
79
 
80
80
  ## Пропсы
81
81
 
@@ -489,7 +489,7 @@
489
489
  <g data-tip="compactAlt">
490
490
  <rect x={VW - 84} y={CY - 16} width="76" height="32" rx="6" fill="#000" fill-opacity="0.55" />
491
491
  <text x={VW - 46} y={CY + 6} text-anchor="middle">{Math.round(alt)}</text>
492
- <text x={VW - 46} y={CY + 32} text-anchor="middle" font-size="11">m · {climb >= 0 ? "+" : ""}{fmt(climb)}</text>
492
+ <text x={VW - 46} y={CY + 32} text-anchor="middle" font-size="11">m · {climb >= 0 ? "+" : ""}{fmt(climb)} m/s</text>
493
493
  </g>
494
494
  </g>
495
495
  {/if}
@@ -556,12 +556,12 @@
556
556
  <!-- Углы под лентами: воздушная и вертикальная скорость -->
557
557
  <g data-tip="airspeed">
558
558
  <rect x="0" y={HH + 6} width={HX - 6} height="44" rx="8" fill="#000" fill-opacity="0.72" />
559
- <text x={(HX - 6) / 2} y={HH + 21} fill="#fff" fill-opacity="0.7" font-size="9" text-anchor="middle">AS</text>
559
+ <text x={(HX - 6) / 2} y={HH + 21} fill="#fff" fill-opacity="0.7" font-size="9" text-anchor="middle">AS m/s</text>
560
560
  <text x={(HX - 6) / 2} y={HH + 41} fill="#fff" font-size="14" font-weight="600" text-anchor="middle">{fmt(as)}</text>
561
561
  </g>
562
562
  <g data-tip="vs">
563
563
  <rect x={HX + HW + 6} y={HH + 6} width={VW - HX - HW - 6} height="44" rx="8" fill="#000" fill-opacity="0.72" />
564
- <text x={(HX + HW + 6 + VW) / 2} y={HH + 21} fill="#fff" fill-opacity="0.7" font-size="9" text-anchor="middle">VS</text>
564
+ <text x={(HX + HW + 6 + VW) / 2} y={HH + 21} fill="#fff" fill-opacity="0.7" font-size="9" text-anchor="middle">VS m/s</text>
565
565
  <text
566
566
  x={(HX + HW + 6 + VW) / 2}
567
567
  y={HH + 41}
@@ -44,7 +44,7 @@ const isDebugLog = (value) => Array.isArray(value) &&
44
44
  !!LOG_LEVELS[value[0]] &&
45
45
  typeof value[1] === "string" &&
46
46
  (typeof value[2] === "string" || value[2] instanceof Uint8Array);
47
- /* Байты строками по 16 — для дампов DebugLog и раздела HEX */
47
+ /* Байты строками по 16 — для дампа DebugLog в Value */
48
48
  const hexRows = (bytes) => (bytesToHex(bytes).match(/.{1,48}/g) ?? []).map((row) => row.trim()).join("\n");
49
49
  const PRETTY_COLORS = {
50
50
  key: "--pink-color",
@@ -201,15 +201,13 @@ export function bindXPoeDebugCopyButtons() {
201
201
  }
202
202
  };
203
203
  }
204
- /* Две прокручиваемые секции модалки: Value — развёрнутый вид Payload в цветах палитры темы, HEX — байты Payload по 16 в строке; HEX-раздел есть, если форматтер таблицы добавил исходные байты */
204
+ /* Две прокручиваемые секции модалки: Value — развёрнутый вид Payload в цветах палитры темы, HEX — исходные байты Payload сплошной строкой; HEX-раздел есть, если форматтер таблицы добавил исходные байты */
205
205
  export function formatXPoeDebugModal(text) {
206
206
  const separator = "\nHEX\n";
207
207
  const hexIndex = text.lastIndexOf(separator);
208
208
  const hex = hexIndex < 0 ? "" : text.slice(hexIndex + separator.length);
209
209
  const pretty = hex ? formatXPoeDebugPrettyHtml(hex) : null;
210
- const bytes = pretty === null ? null : hexToBytes(hex);
211
210
  const decoded = pretty === null ? (hexIndex < 0 ? text : text.slice(0, hexIndex)) : pretty;
212
- const hexText = bytes ? hexRows(bytes) : hex;
213
211
  const modalStyle = "display:flex;flex-direction:column;gap:.75rem;max-height:80vh;min-width:0;overflow-y:auto;overflow-x:hidden";
214
212
  const sectionStyle = "min-width:0;padding:.25rem 0 .75rem";
215
213
  const headingStyle = "display:flex;align-items:center;justify-content:space-between;gap:.75rem;margin:0 0 .5rem;font-weight:600";
@@ -217,5 +215,5 @@ export function formatXPoeDebugModal(text) {
217
215
  const buttonClass = "flex size-7 cursor-pointer items-center justify-center rounded-lg border-none bg-transparent text-(--faint-color) transition-colors duration-150 hover:bg-(--container-color) hover:text-(--font-color)";
218
216
  const textStyle = "display:block;min-width:0;max-width:100%;margin:0;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;font:inherit";
219
217
  const pane = (title, target, value) => `<section style="${sectionStyle}"><div style="${headingStyle}"><span>${title}</span><button type="button" class="${buttonClass}" data-xpoe-copy="${target}" aria-label="Копировать ${title}" style="${buttonStyle}">${COPY_ICON}</button></div><pre style="${textStyle}">${value}</pre></section>`;
220
- return `<div data-xpoe-debug-modal style="${modalStyle}">${pane("Value", "value", decoded)}${hexIndex < 0 ? "" : pane("HEX", "hex", hexText)}</div>`;
218
+ return `<div data-xpoe-debug-modal style="${modalStyle}">${pane("Value", "value", decoded)}${hexIndex < 0 ? "" : pane("HEX", "hex", hex)}</div>`;
221
219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-svelte-ui-lib",
3
- "version": "1.79.0",
3
+ "version": "1.79.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Oleg-Perevyshin/ElementsUI.git"