Формат файла .ttag
Файл обмена инвентарём .ttag — это переносимый офлайн-снимок одного или
нескольких материалов инвентаря. Он служит единицей для резервного
копирования ваших филаментов, переноса их на USB-накопителе и обмена
ими — между аккаунтами, между инструментами или в виде готовых коллекций
брендов и линеек.
Появился в Tiger Studio Manager v2.14.0 (экспорт и импорт). Формат
стабилен и общий для приложений: на этой спецификации строятся сторонние
инструменты, будущая веб-песочница, генерирующая файлы .ttag, и готовые
коллекции филаментов.
Структура файла
Заголовок раздела «Структура файла»Файл .ttag — это один документ UTF-8 JSON:
{ "format": "tigertag", "kind": "ttag", "version": 1, "exportedAt": "2026-07-24T00:00:00.000Z", "exportedBy": "<owner uid>", "records": [ /* inventory documents, verbatim */ ], "rfidBackups": { "<chipUid>": { /* chip content from its first read */ } }}| Поле | Значение |
|---|---|
format / kind |
Всегда "tigertag" / "ttag" — пара-идентификатор, проверяемая при импорте |
version |
Версия формата; сейчас 1 |
exportedAt |
Время экспорта, строка ISO 8601 (например, "2026-07-24T00:00:00.000Z") |
exportedBy |
uid экспортирующего владельца — подсказка для интерфейса при выборе режима импорта, и ТОЛЬКО она; никогда не граница безопасности |
records[] |
Документы инвентаря, переносимые дословно |
rfidBackups |
Необязательно. Ключ — UID чипа; присутствует только для чипов, у которых есть резервная копия, — содержимое чипа в том виде, в каком Tiger Studio впервые прочитала его с TigerTag+ (с подписью у TigerTag+ Certified), используемое для восстановления чипа |
records[] — это документы инвентаря Firestore, дословно — ровно
users/{uid}/inventory/{spoolId}, как описано в
каноничной модели данных
(используйте её как словарь полей). Три нюанса:
- Поля разрежены — поле записывается, только если оно есть в документе:
twin_tag_uidтолько у двойников,rfidBackup: trueтолько у чипа с резервной копией,id_productтолько если он известен, и так далее. - Поля-URL контролируются злоумышленником —
LinkTDS,LinkMSDS,LinkYoutube,LinkREACH,LinkROHS,LinkFOODиurl_img*очищаются при импорте: любая схема, кроме http(s), отбрасывается. - Место на стеллаже переносится, но не применяется —
rack,rack_id,level,positionмогут присутствовать в файле, но при импорте не имеют значения (импортированная катушка не наследует стеллаж экспортёра).
Обязательные и необязательные поля
Заголовок раздела «Обязательные и необязательные поля»На уровне файла:
| Поле | Статус |
|---|---|
format = "tigertag", kind = "ttag", version ≤ 1 |
Обязательно — отсутствие или несоответствие = файл отклоняется |
records[], непустой |
Обязательно — пустой файл отклоняется |
exportedAt, exportedBy |
Информативные (exportedBy — только подсказка для интерфейса) |
rfidBackups |
Необязательно — присутствует только если включены чипы с резервной копией |
На уровне записи:
| Категория | Поля |
|---|---|
| Обязательно | uid (TigerData_<id> или UID чипа) · id_brand |
| Основная идентичность (есть в каждой корректной записи) | id_material, id_type, id_aspect1, id_tigertag — разрешаются по общей справочной базе данных |
| Ёмкость | Нормализуется из measure + id_unit: measure_gr в граммах для твёрдых материалов (например, measure: 1 + кг → measure_gr: 1000) и measure_ml в миллилитрах для жидких (смолы). Генераторы могут указывать measure + id_unit; нормализованное значение — каноническое хранимое |
| Типичные необязательные | поля цвета (color_r/g/b, online_color_list…), weight_available, container_id / container_weight, отображаемые строки (material, series, color_name), TD, tags, sku / barcode, Link*, url_img* |
| Условные | twin_tag_uid (только у двойников — взаимный внутри файла) · tag_index / tag_count (только записи с чипом — чип i из n, считывается из байта чипа +39, протокол TigerTag v2.2; по одному полубайту, 0 = неизвестно; никогда не у записи без чипа) · rfidBackup: true плюс соответствующая запись rfidBackups (только чипы с резервной копией) · id_product (только для известных продуктов каталога) |
| Переносятся, но игнорируются при импорте | rack, rack_id, level, position |
Для любого граничного случая, не описанного здесь, эталонной реализацией является импортёр Tiger Studio — сторонним генераторам следует стремиться к записям, которые принимает стандартная Studio.
Правила, заложенные в формат:
- Два соглашения о метках времени — намеренно. Корневое
exportedAt— это строка ISO 8601. Метки времени внутриrecords[](updatedAtи устаревшие вариантыupdated_at/last_update) — это числа в эпохальных миллисекундах: Firestore Timestamps преобразуются сериализатором, чтобы файл чисто сериализовался. Не «исправляйте» одно под другое: файлы в обращении уже имеют именно такую форму. - Двойники атомарны. Материал-двойник всегда экспортирует обе
стороны — один материал → две записи, связанные
twin_tag_uid. Половина двойника никогда не создаётся. - Дисциплина идентификаторов. Могут встречаться только id
TigerData_<id>без чипа; устаревший idCLOUD_<id>отвергается при экспорте.
Контейнеры (container_id, container_weight)
Заголовок раздела «Контейнеры (container_id, container_weight)»container_id указывает пустую катушку, на которой намотан филамент.
container_weight — вес этой пустой катушки в граммах: тара, которую весы
вычитают, чтобы инвентарь показывал чистый филамент.
Идентификаторы — это строки из одного фиксированного списка, поставляемого с
Tiger Studio: data/container_spool/spools_filament.json.
Каждая запись содержит бренд, к которому она относится (brandId, то же
число, что и id_brand), и каталожный вес. Большинство — собственная катушка
бренда: bambu_grey (249 г), esun_masterspool_2_0 (210 г),
polymaker_cardboard (170 г); три — универсальные, для бренда, чьей катушки
ещё нет в списке:
container_id |
Как показывает Tiger Studio | Каталожный вес |
|---|---|---|
custom_cardboard |
Generic · Cardboard | 165 г |
custom_plastic |
Generic · Plastic | 200 г |
custom_no_masterspool |
Generic · Refill — Without MasterSpool | 0 г |
custom_no_masterspool ничего не вычитает. Он верен для рефилла, который
взвешивают без катушки, и неверен во всех остальных случаях: катушка с ним
показывает вес брутто, примерно на 200 г больше оставшегося филамента.
container_weight — это снимок, сделанный в момент выбора контейнера, а
не поиск по списку. Запись сохраняет своё значение, когда список меняется, а
аккаунт может исправить вес контейнера для своих катушек (хранится в
users/{uid}/containerOverrides/{id}; общий список никогда не изменяется).
Генератор, который знает пустую катушку, записывает оба поля. Тот, который не знает, опускает их, а не угадывает: тогда Tiger Studio ставит собственный контейнер бренда или спрашивает, если их несколько или нет ни одного.
Тип носителя
Заголовок раздела «Тип носителя»Каноничный тип носителя — application/vnd.tigertag.ttag+json; он важен
там, где .ttag отдаётся по http(s) (Content-Type, который должны
отправлять веб-песочница, CDN или хост коллекции брендов).
application/json тоже принимается. Файл на диске не несёт MIME — он
определяется по расширению .ttag и, окончательно, по содержимому:
импортёры проверяют по содержимому (format/kind/version), но никогда
только по заголовку MIME или расширению файла.
Доступность
Заголовок раздела «Доступность»Экспорт и импорт поставляются в Tiger Studio v2.14.0+. Формат задуман переносимым; другие поверхности могут принять его со временем — сегодня эталонная реализация — Studio.
Что может нести .ttag
Заголовок раздела «Что может нести .ttag»Экспортируются и импортируются все три уровня катушек:
| Уровень | В файле |
|---|---|
| TigerData (полностью цифровая, без чипа) | Сама запись |
| TigerTag (записанный чип) | Сама запись |
| TigerTag+ (подписанный или нет) | Запись плюс резервная копия чипа в rfidBackups |
Tiger Studio делает резервную копию при первом чтении чипа TigerTag+, подписанного или нет, и никогда её не перезаписывает. У TigerTag+ Certified копия содержит подпись, поэтому восстановленный чип остаётся Certified.
Экспорт
Заголовок раздела «Экспорт»- Одна катушка — из панели инструментов сведений о катушке → файл с
именем
brand-material-color.ttag. - Множественный выбор — выберите несколько катушек, кнопка Экспорт на
панели → файл с именем
tigertag-selection-<date>.ttag. - Экспорт доступен только для собственного инвентаря пользователя.
Импорт — проверка → предпросмотр → принятие
Заголовок раздела «Импорт — проверка → предпросмотр → принятие»Импортёр принимает несколько файлов .ttag одновременно: выберите
обзором, вставьте ссылку http(s) или перетащите в любое место окна.
- Проверка. Каждый файл должен нести пару
format/kindиversion ≤ 1. Файл не.ttag, более новая версия или пустой файл отклоняются. Затем каждая запись должна нести полную полезную нагрузку чипа — см. Обязательные поля ниже. - Очистка. Содержимое файла — недоверенный ввод: поля-URL не с http(s) отбрасываются; значения цвета, веса и TD ограничиваются допустимыми диапазонами.
- Предпросмотр. Каждый материал показывается в таблице предпросмотра с флажком включения для каждого материала.
- Принятие в одном из двух режимов — предподсказанном по
exportedBy, свободно переключаемом:
| Восстановление | Импорт | |
|---|---|---|
| Назначение | Тот же аккаунт / настоящее восстановление | Принятие чужих материалов |
| Id записей | Сохраняются — записываются дословно под исходными id | Новые id — каждая запись становится новой катушкой TigerData_ без чипа, принадлежащей импортирующему |
| Статус чипа | Сохраняется — каждая резервная копия rfidList восстанавливается |
Теряется — копия без чипа: id_tigertag удаляется, rfidBackup:false, резервные копии отбрасываются (резервная копия принадлежит чипу, которого у импортирующего нет) |
| Продукт | Сохраняется | Сохраняется, если id_product — реальный id из каталога (не 0 и не 0xFFFFFFFF), так что TigerData+ остаётся TigerData+, а TigerTag+ приходит как TigerData+ того же продукта; всё остальное устанавливается в 0xFFFFFFFF (не задан). До Tiger Studio v2.51.1 он всегда сбрасывался, так что TigerData+ приходил как обычный TigerData |
| Вес | Как записано | Сбрасывается до полной ёмкости |
| Двойники | Как записано | twin_tag_uid переназначается через новые id |
Обязательные поля — по записи должно получаться создать чип
Заголовок раздела «Обязательные поля — по записи должно получаться создать чип».ttag существует, чтобы создавать чипы TigerTag / TigerTag+. Запись, не
способная создать чип, — не частичная запись, а непригодная, поэтому начиная с
Tiger Studio 2.15.0 импортёр отвергает её сразу, вместо того чтобы
импортировать катушку, которая выглядит нормально, но молча неверна.
Запись принимается, только если несёт uid плюс эти 24 числовых поля,
каждое присутствует и конечно (null и "" не считаются присутствием —
осторожно, Number(null) равно 0):
| Группа | Поля |
|---|---|
| Идентификаторы идентичности | id_brand, id_material, id_type, id_aspect1, id_aspect2, id_diameter, id_measure_unit, id_version, id_product |
| Количество | measure |
| Цвет | color_r, color_g, color_b, color_a |
| Данные по типу | data1 … data7 |
| Штамп | timestamp |
Плюс id_tigertag, но только если у записи есть чип. Это поле называет
версию чипа в id_version.json, где допустимы ровно четыре значения: 0
RFID Empty, 1542820452 TigerTag, 1816240865 TigerTag Init, 3155151767
TigerTag+. У записи без чипа (uid начинается с TigerData_ или с
устаревшего CLOUD_) нет чипа и, следовательно, версии, поэтому она не
должна нести это поле вовсе; оно записывается впервые, когда программируется
настоящий чип. Никогда не придумывайте для него значение и никогда не
разрешайте его, не проверив, что у записи есть чип.
Всё остальное в записи — названия, изображения, цена, заметки, место на стеллаже — это обогащение: приятно переносить, но никогда не обязательно.
Материал атомарен. Пара двойников проходит, только если проходят обе её записи; наполовину корректный двойник отвергается целиком, потому что импорт одной стороны пары создал бы катушку, партнёр которой никогда не сможет быть записан.
Отказы подсчитываются и показываются, они не молчаливы. Предпросмотр
сообщает, сколько материалов было отвергнуто, так что плохой экспорт виден, а
не тихо теряет половину содержимого. Авторам файлов .ttag следует проверять
их по этому списку, прежде чем отдавать файл пользователям.
Полный пример
Заголовок раздела «Полный пример»Достоверный анонимизированный экспорт множественного выбора — одна TigerData,
одна пара двойников (взаимный twin_tag_uid), одна TigerTag+, содержимое чипа
которой сохранено в резервной копии:
{ "format": "tigertag", "kind": "ttag", "version": 1, "exportedAt": "2026-07-24T00:00:00.000Z", "exportedBy": "AbCdEf0123456789GhIjKlMnOpQr", "records": [ { "uid": "TigerData_9F3A2B1C", "id_brand": 12, "id_material": 3, "id_type": 1, "id_aspect1": 2, "id_aspect2": 0, "id_tigertag": 74213, "material": "PLA Basic", "color_name": "Sky Blue", "color_r": 88, "color_g": 170, "color_b": 220, "online_color_list": "58AADC", "online_color_type": 1, "measure_gr": 1000, "weight_available": 640, "container_id": "custom_plastic", "container_weight": 200, "TD": 0, "tags": ["desk", "prototyping"], "rfidBackup": false, "updatedAt": 1769212800000 }, { "uid": "04A1B2C3D4E5F6", "id_brand": 5, "id_material": 3, "id_type": 1, "id_aspect1": 4, "id_tigertag": 55010, "material": "PLA Silk", "color_name": "Gold", "color_r": 212, "color_g": 175, "color_b": 55, "online_color_list": "D4AF37", "measure_gr": 1000, "weight_available": 500, "container_id": "custom_plastic", "container_weight": 200, "twin_tag_uid": "04F6E5D4C3B2A1", "tag_index": 1, "tag_count": 2, "rfidBackup": false, "updatedAt": 1769212800000 }, { "uid": "04F6E5D4C3B2A1", "id_brand": 5, "id_material": 3, "id_type": 1, "id_aspect1": 4, "id_tigertag": 55011, "material": "PLA Silk", "color_name": "Emerald", "color_r": 0, "color_g": 130, "color_b": 90, "online_color_list": "00825A", "measure_gr": 1000, "weight_available": 500, "container_id": "custom_plastic", "container_weight": 200, "twin_tag_uid": "04A1B2C3D4E5F6", "tag_index": 2, "tag_count": 2, "rfidBackup": false, "updatedAt": 1769212800000 }, { "uid": "04112233445566", "id_brand": 5, "id_material": 8, "id_type": 1, "id_aspect1": 2, "id_tigertag": 90887, "id_product": 4412, "material": "PETG HF Basic", "series": "Hyper PETG", "color_name": "Green", "color_r": 0, "color_g": 160, "color_b": 70, "online_color_list": "00A046", "measure_gr": 1000, "weight_available": 480, "container_id": "custom_plastic", "container_weight": 200, "TD": 6, "LinkTDS": "https://example-brand.example/tds/petg-hf-basic.pdf", "sku": "RFHPPETG175GN1", "rfidBackup": true, "updatedAt": 1769212800000 } ], "rfidBackups": { "04112233445566": { "firstSeen": 1767139200000, "backup": "0411223344556680048000000000E110122F0300FE0000A5A5C0FFEE112233445566778899…" } }}Как читать пример: первая запись без чипа (id TigerData_); следующие две —
пара двойников — тот же материал, взаимный twin_tag_uid, всегда
экспортируются вместе; последняя — TigerTag+ (rfidBackup: true), чья
резервная копия лежит в rfidBackups под UID её чипа.
Безопасность / модель доверия
Заголовок раздела «Безопасность / модель доверия»Файл .ttag — недоверенный ввод. Каждая запись очищается при импорте
(см. выше). exportedBy лишь предварительно выбирает режим в интерфейсе —
настоящая граница авторизации — это правила безопасности Firestore.
Никогда не считайте содержимое файла авторитетным в вопросах идентичности или
владения.
См. также: Универсальная идентичность филамента, Инвентарь и облачная синхронизация, Обзор для разработчиков