Перейти к содержимому
Эта страница переведена автоматически с английского. Сообщите об ошибке или предложите исправление.

Формат файла .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> без чипа; устаревший id CLOUD_<id> отвергается при экспорте.

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.

Экспортируются и импортируются все три уровня катушек:

Уровень В файле
TigerData (полностью цифровая, без чипа) Сама запись
TigerTag (записанный чип) Сама запись
TigerTag+ (подписанный или нет) Запись плюс резервная копия чипа в rfidBackups

Tiger Studio делает резервную копию при первом чтении чипа TigerTag+, подписанного или нет, и никогда её не перезаписывает. У TigerTag+ Certified копия содержит подпись, поэтому восстановленный чип остаётся Certified.

  • Одна катушка — из панели инструментов сведений о катушке → файл с именем brand-material-color.ttag.
  • Множественный выбор — выберите несколько катушек, кнопка Экспорт на панели → файл с именем tigertag-selection-<date>.ttag.
  • Экспорт доступен только для собственного инвентаря пользователя.

Импорт — проверка → предпросмотр → принятие

Заголовок раздела «Импорт — проверка → предпросмотр → принятие»

Импортёр принимает несколько файлов .ttag одновременно: выберите обзором, вставьте ссылку http(s) или перетащите в любое место окна.

  1. Проверка. Каждый файл должен нести пару format/kind и version ≤ 1. Файл не .ttag, более новая версия или пустой файл отклоняются. Затем каждая запись должна нести полную полезную нагрузку чипа — см. Обязательные поля ниже.
  2. Очистка. Содержимое файла — недоверенный ввод: поля-URL не с http(s) отбрасываются; значения цвета, веса и TD ограничиваются допустимыми диапазонами.
  3. Предпросмотр. Каждый материал показывается в таблице предпросмотра с флажком включения для каждого материала.
  4. Принятие в одном из двух режимов — предподсказанном по 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. Никогда не считайте содержимое файла авторитетным в вопросах идентичности или владения.


См. также: Универсальная идентичность филамента, Инвентарь и облачная синхронизация, Обзор для разработчиков