Несколько касс на одном ТС ПИоТ: экземпляры, порты и API оркестратора

Одна касса на кассовом узле — простой случай, он закрывается обычной установкой. Когда касс несколько, появляется отдельный слой: для каждой создаётся свой экземпляр ТС ПИоТ со своим набором портов.

Команды ниже предназначены для PowerShell. Перенос через обратный слеш из примеров Linux здесь не используется. Не публикуйте ответы с учётными данными: запрос настроек ЛМ возвращает логин и пароль открытым текстом.

Настраивается это не мышкой, а запросами к оркестратору. Разберём порядок и особенность, которая для касс АТОЛ упрощает схему.

Как это устроено

Несколько касс на одном ТС ПИоТ: экземпляры модуля, порты и контроллер
Кассы разные, экземпляры свои, а контроллер и локальный модуль на всех одни

Ниже — порядок настройки и условие, без которого схема не соберётся.

Условие, о котором нужно знать заранее

Все кассы должны быть оформлены на один ИНН. Это не рекомендация: при попытке зарегистрировать экземпляр для кассы с другим ИНН оркестратор вернёт ошибку 1026 «Обнаружено несколько ИНН».

Режим работы с несколькими кассами поддержан со стороны драйвера АТОЛ. У некоторых других вендоров поддержка на момент выхода инструкции ещё ожидалась.

Три порта на каждый экземпляр

У каждого экземпляра ТС ПИоТ есть идентификатор и три порта:

ПараметрЧто это
portПорт экземпляра, по которому с ним общается оркестратор
softPortПорт API проверки кодов — к нему обращается кассовая программа
dkktPortgRPC-порт драйвера, к которому подключается экземпляр

Если softPort при создании не передать, он приравнивается к нулю, и кассовая программа будет подключаться на порт по умолчанию — 51401.

Ниже пример для трёх касс АТОЛ через один gRPC-сервис на порту 4042. Все идентификаторы и реквизиты в командах замените данными своих устройств.

Свойства драйвера ККТ АТОЛ: раскрытый список COM-портов
Настройки канала связи в утилите; снимок не устанавливает процесс-владелец занятого порта
КассаidportsoftPortdkktPort
№1012824562150401514014042
№2012824562250402514024042
№3012824562350403514034042

Для второй и последующих касс port и softPort указывать обязательно — иначе они конфликтуют между собой.

Особенность АТОЛ: один сервис на все кассы

Здесь схема для АТОЛ заметно проще общей.

Несколько касс могут обслуживаться одним gRPC-сервисом на одном порту. Если сервис слушает, скажем, 4042, и через него доступны три кассы, то все три будут отображаться с одинаковым dkktPort = 4042.

Отдельный gRPC-порт под каждую кассу не нужен. Сервис возвращает массив касс, а оркестратор добавляет их все в общий список. Проверить, что получилось, можно запросом GET /api/v1/dkktList.

Параметр dkktPort при этом сохраняет смысл: он показывает, через какой экземпляр драйвера обслуживается конкретная касса.

Что должно быть готово

  • Один или несколько экземпляров драйвера запущены и принимают gRPC-подключения.
  • Для каждого экземпляра драйвера определён gRPC-порт. Если экземпляров несколько, их порты не должны пересекаться.
  • Оркестратор доступен по адресу http://127.0.0.1:51077.
  • Для каждого экземпляра ТС ПИоТ выбраны уникальные port и softPort.

Шаг 1. Создать экземпляр

$body = @{id="0128245622"; port=50402; softPort=51402; dkktPort=4042} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:51077/api/v1/tspiot" -ContentType "application/json" -Body $body

В качестве id используется идентификатор создаваемого экземпляра — как правило, заводской номер кассы.

HTTP 201 подтверждает создание экземпляра. Значение serviceState говорит только о состоянии службы. Регистрация, лицензия, привязка кассы и удачная проверка из клиента — четыре отдельных пункта, и каждый нужно смотреть сам по себе.

Шаг 2. Зарегистрировать экземпляр

Создание — это ещё не регистрация. Для каждой новой кассы после создания экземпляра выполняется отдельный запрос с её реквизитами:

$body = @{id="0128245622"; kktSerial="0128245622"; fnSerial="9999000000001051"; kktInn="9717169631"} | ConvertTo-Json
Invoke-RestMethod -Method Put -Uri "http://127.0.0.1:51077/api/v1/tspiot" -ContentType "application/json" -Body $body

Ответ содержит tspiotId — идентификатор зарегистрированного экземпляра.

Шаг 3. Привязать локальный модуль

Для второго экземпляра 0128245622 общий драйвер доступен на 4042, API проверки ЕСМ — на 51402. Следующий запрос связывает этот экземпляр с локальным модулем. Указывается адрес и порт Контроллера ЛМ ЧЗ — 50063, а не порт самого модуля; это отдельная настройка, не dkktPort.

$credential = Get-Credential -Message "Учётные данные ЛМ ЧЗ"
$body = @{address="192.168.1.117"; port=50063; login=$credential.UserName; password=$credential.GetNetworkCredential().Password} | ConvertTo-Json
Invoke-RestMethod -Method Put -Uri "http://127.0.0.1:51077/api/v1/settings/lm/0128245622" -ContentType "application/json" -Body $body

В поле address — машина, на которой стоят локальный модуль и контроллер. Если они на том же компьютере, что и ЕСМ, это 127.0.0.1; если на отдельном сервере — его адрес.

Настройка применяется сразу, перезапускать экземпляр не нужно.

Число экземпляров ЛМ и схема их привязки должны соответствовать инструкции используемого комплекта. Пример с отдельными портами не является подтверждением, что один общий ЛМ допустим для любого набора касс. До изменения проверьте идентичность экземпляров, реквизиты организации и требования интеграции.

Обратите внимание: здесь указывается порт контроллера — 50063, а не порт самого локального модуля. Путаница этих двух портов — самая частая ошибка настройки.

Ошибка распознаётся сразу. Если передать порт модуля — 5995 вместо 50063, — оркестратор ответит:

{"error":{"code":2025,"text":"error 2025: ЛМ контроллер не найден"}}

Текст ошибки говорит буквально: по указанному адресу ищут контроллер и не находят его. Проверено на рабочей установке с двумя кассами.

Шаг 4. Проверить результат

Список экземпляров:

Invoke-RestMethod -Uri "http://127.0.0.1:51077/api/v1/instances/info"

Подробности по конкретному:

Invoke-RestMethod -Uri "http://127.0.0.1:51077/api/v1/instances/info/0128245622"

В ответе смотрите clientPort — он должен совпадать с указанным softPort — и блок regData с реквизитами кассы.

Приёмка каждой строки таблицы: сверьте физическую ККТ → её заводской номер → id экземпляра → clientPort → настройку конкретной кассы в приложении. Выполните отдельную контрольную проверку по каждому маршруту и сопоставьте журнал. Первая касса заработала — со второй это ничего не обещает. Приведённые номера — пример конфигурации, а не протокол испытания трёх касс.

До изменения или удаления одного экземпляра сохраните его параметры и список остальных. Выбирайте операцию по точному id и контракту API своей версии, затем повторно прочитайте список и проверьте, что соседние экземпляры не изменились. Не используйте массовую очистку для исправления одной строки.

Какой локальный модуль привязан:

Invoke-RestMethod -Uri "http://127.0.0.1:51077/api/v1/settings/lm/0128245622"

Ответ содержит логин и пароль в открытом виде. Учитывайте это, если пересылаете вывод в поддержку или прикладываете логи.

Работоспособность самого контроллера проверяется запросом GET /api/v1/instances/lm/{id} — он возвращает версию, состояние и сведения об ОС, но не адрес подключения.

Как обращается кассовая программа

После создания и регистрации кассовая программа обращается к API проверки кодов по тому softPort, который был указан. Для второй кассы из примера адрес будет таким:

http://127.0.0.1:51402/api/v3/codes/check

То есть у каждой кассы свой адрес проверки. Это нужно прописать в настройках кассового ПО — в Frontol это поле «Порт ЕСМ», в 1С — порт в настройках подключения к ТС ПИоТ.

Коды ошибок оркестратора

Сохраняйте HTTP-статус и прикладные поля code, text, description вместе. Номер удобен для поиска, но без источника и текста совпадающие коды разных компонентов легко перепутать.

КодHTTPЧто означает
1001400Некорректное тело запроса
1002400Некорректный параметр запроса
1009500Ошибка создания, удаления или изменения службы
1010400Служба с таким именем уже существует
1012400Служба с таким именем не создана
1013500Служба не была запущена
1015500, 204Не запущен агент-сервис драйвера
1022500Получена ошибка от сервиса ЕСМ
1023204Не найдено ни одной зарегистрированной службы
1026403Обнаружено несколько ИНН
1000500Неизвестная ошибка

Коды вида 20xx приходят из слоя работы с модулем, и текст у них начинается с префикса error — например, «error 2046: Служба ЕСМ либо не зарегистрирована, либо не запущена». Их разбор — в статье про ошибки ЕСМ.

Частые вопросы

Обязательно через API? Здесь описана API-процедура из инструкции от 24.06.2026. Наличие интерфейса в более новой версии проверяйте отдельно; команды не переносите между версиями без сверки контракта.

Сколько касс можно подключить? В этой статье универсальный предел не подтверждён. Один ИНН и разные порты — обязательные условия этой схемы. Но и при них стоит проверить, тянет ли ваш комплект такую нагрузку.

Можно ли обойтись без отдельных экземпляров? Для АТОЛ упрощается только часть с драйвером: один gRPC-сервис на все кассы. Экземпляр ТС ПИоТ на каждую кассу нужен всё равно.

Нужна ли отдельная лицензия на каждую кассу? Да, лицензия привязывается к кассе, а не к организации. Подробности — на странице загрузки ЕСМ.

Физическое подключение. Для каждой ККТ нужен однозначный адрес в выбранном транспорте: например, отдельный COM-порт при такой схеме или сетевой адрес для TCP. Требование собственного COM-порта не распространяется на все способы связи.

Коротко

Каждой кассе — свой экземпляр ТС ПИоТ с уникальными port и softPort. Создаётся POST-запросом к оркестратору на 127.0.0.1:51077, регистрируется PUT-запросом с реквизитами кассы, локальный модуль привязывается отдельным запросом. Для АТОЛ есть послабление: все кассы могут обслуживаться одним gRPC-сервисом драйвера на общем порту. Жёсткое условие — все кассы на один ИНН, иначе ошибка 1026. Кассовая программа обращается к каждой кассе по её собственному softPort.


Материал носит информационный характер. Сайт atoldriver.ru не является представительством компании АТОЛ или АО «ЕСП» и не оказывает услуг по обслуживанию оборудования.