# База знаний по проекту Честный знак
## Ссылки на ресурсы
* https://честныйзнак.рф
* https://www.gs1ru.org - Ассоциация автоматической идентификации GS1
* https://markirovka.ru/
* https://markirovka.sandbox.crptech.ru/login-kep - Тестовый контур «Песочница»
* https://markirovka.ru/community/beer_producers/korobochnoe-reshenie-dlya-markirovki-hi-mark-lite - страница по HiMark
* https://up-line.online/ - оф.сайт HiMark
* https://mercury.vetrf.ru/ - оф. сайт Меркурий (система государственного ветеринарного надзора)
* https://ru.wikipedia.org/wiki/Меркурий_(информационная_система) - статья по ФГИС Меркурий
## Материалы по теме
* https://habr.com/ru/post/550466/ - описан хороший подробный план по внедрению маркировки на производстве и недостатки модуля 1С
* https://habr.com/ru/search/?target_type=posts&order=relevance&q=%5Bчестный%20знак%5D - поиск по тегу ЧЗ
## Термины и аббревиатуры
* ВСД - ветеринарно-сопроводительный документ
* ГИС МТ - Государственная информационная система мониторинга товаров в России "Честный знак".
* Код маркировки (КМ) - Уникальный номер, который состоит из кода идентификации и кода проверки. По нему можно получить всю информацию о продукте и его движении. Формирует ГИС МТ.
* Код идентификации (КИ) - Уникальный номер одного экземпляра товара. Его формирует ГИС МТ.
* Код проверки (КП) - Уникальный номер, который позволяет выявить подделку кода идентификации. Его формирует ГИС МТ.
* Модельный ряд - состав однородной продукции по видам, сортам и маркам. Может быть связан с ОКП. Например, по ОКП: 04.04 - Молоко и сливки с содержанием жира более 6%.
* ОКП - общероссийский классификатор продукции, это единая система классификации товаров, которая используется для стандартизации и упрощения процесса обработки информации о продукции.
* ПЛ - производственная линия, комплекс оборудования и технологических процессов, предназначенных для приема, переработки и упаковки молока и молочных продуктов.
* ПЛК - программируемый логический контроллер, управляет датчиками, например, датчик обраковщика (даёт сигнал отбраковщику скинуть продукты) и тд.
* Средство идентификации (СИ) - Двумерный штрихкод в формате DataMatrix, который наносят на товар или упаковку.
* Станция управления заказами (СУЗ) - подмодуль ГИС МТ
* ЦРПТ - Центр развития перспективных технологий, в частности они создали Честный знак.
* DataMatrix - двумерный графический код, похож на QR-код, в отличие от него может хранить больше информации, более криптостойкий, и имеет запас устойчивости до 30 % (если будет повреждён, например, при неправильной траспортировке)
* GTIN (Global Trade Item Number) - Идентификационный номер товара, который получают на сайте ГС1 РУС для каждого модельного ряда.
* остальное https://sbis.ru/help/data_exchange/marking/dictionary
## Прообразы разрабатываемой системы
* личный кабинет на сайте ГИС МТ (вероятно, избыточный функционал - нам не нужны СЭД, чеки и др.функции)
* ПО HiMark (в данный момент используется на УГМЗ)
## Нефункциональные требования
* обеспечение нанесения и считывания маркировки, а также отбраковки на скорости 6 тыс. ед. продукции в час (линия ПЭТ)
* с системой будут работать несколько пользователей, имеющих разные роли
## Функции системы
1) Осуществление заказов на эмиссию кодов маркировки.
2) Предоставление эмитированных кодов маркировки для нанесения на продукцию.
3) Верификацию нанесения КМ.
4) Агрегацию готовой, упакованной продукции с нанесёнными средствами идентификации (СИ).
5) Списание бракованной продукции.
1) Получение заказов и предоставление эмитированных кодов маркировки.
2) Получение уведомлений об использовании (нанесении) кодов маркировки и регистрация статуса кодов маркировки в Системе товарной группы (Честный знак).
3) Получение уведомлений об агрегации кодов маркировки и регистрация агрегации упакованной продукции в Системе товарной группы.
4) Получение уведомлений об отбраковки продукции и регистрация отбракованной продукции в Системе товарной группы.
п. 1.1 Руководства программиста
## Диаграмма развёртывания (структурная схема)

## Диаграмма состояний КМ

## Алгоритм валидации КМ

## Алгоритм проверки на дубликаты
1. Если код имеет один из статусов (Expired, Invalid, Valid), то создаём запись сущности Reject (Брак), причина "дубликат".
### Примечания
* Модуль диспетчеризации запросов может быть реализован как стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль синхронизации данных - можно реализовать с помощью стандартных механизмов PostgreSQL
* Модуль интеграции с ЧЗ и АРМ администратора взаимодействуют через стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль диспетчеризации и АРМ оператора взаимодействуют через стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль диспетчеризации взаимодействует с модулями аппаратной части через соответствующие протоколы (TCP и тд)
# Режимы запуска
## Режим отладки:
* запуск установки,
* коды печатаются,
* отбраковщик не пропускает товар.
* Мы не фиксируем эти коды.
Интерфейс - либо отдельной кнопкой, либо галочку.
Также есть переключатель на физическом уровне.
Если не совпадает логический и физический режимы, то выводим сообщение “…”.
## Режим работа:
* наносим коды
* считываем коды
* отбраковщик работает
С возможностью аварийного стопа. В этом случае останавливаем производственную линию.
## Структура кода маркировки для молочной продукции
Длина кода (включая символы GS) - 31
Потребительская и групповая упаковка
• AI01–2
• Код товара – 14
• AI21–2
• Серийный номер – 1 символ код страны + 5 символов S/N + 1 символ <GS>
• AI93–2
• Код проверки – 4
Состав кодов маркировки DataMatrix молочных продуктов
Расшифровка кода маркировки молока и молочной продукции это процедура идентификации. Идентификация молочной продукции происходит по четырем группам данных AI (идентификаторы применения) в соответствии со стандартом GS1 DataMatrix.
* В начале каждого кода маркировки всегда присутствует символ GS1 DataMatrix FNC1 (ASCll 232).
* Первая группа. Al (01) состоит из 14 цифр и содержит код товара.
* Вторая группа. Al (21) состоит из 6 символов и содержит индивидуальный серийный номер упаковки товара. Заканчивается разделителем FNC1 (ASCII 29).
* Третья группа (является опциональной).
** Если срок хранения продукта более 72 часов, то используется Al (17), состоящий из 6 цифр: ГГММДД.
** Если срок хранения продукта менее 72 часов, то используется Al (73), состоящий из 10 цифр: ГГММДДЧЧММ.
* Четвертая группа. Al (93) состоит из 4-х символов и содержит код проверки.
## ПО
Программа для настройки веб-камеры: AMCap https://amcap.ru.uptodown.com/windows/download
## Материалы
* Описание структуры кодов датаматрикс: https://честныйзнак.рф/upload/Структура%20DataMatrix.pdf
* Состав кодов маркировки DataMatrix молочных продуктов: https://getmark.ru/blog/o-markirovke/kod-markirovki-molochnoj-produkcii-chto-soderzhit-rasshifrovka/
* Работа с модулём ввода-вывода https://owen-prom.ru/files/re_mk210-301-311_1-ru-22947-1.15.pdf
## Delta камера
* Ip-адрес:192.168.0.210
* логин, пароль от веб клиента: admin, admin
# Сканирование детали
размер кадра в мм:
* по горизонтали 57.5
* по вертикали 38 мм
## Состав модулей системы
* модуль связи с ГИС МТ (должен выполнятся на Windows)
* АРМ администратора
* модуль интеграции с аппаратным блоком ввода-вывода дискретных сигналов (для работы с датчиком наличия продукта на линии и отбраковщиком)
* модуль получения считанных КМ с камеры
* модуль печати КМ на принтере
* АРМ оператора
## Схема получения авторизационного токена ГИС МТ
* отправляется GET запрос на URL https://sandbox.crptech.ru/api/v3/auth/cert/key, в ответ в формате json приходят 2 параметра: uuid и data
Пример:
{
"uuid": "4565e659-87c7-466e-b102-a50bc1bda44f",
"data": "SHZNTAOGVKXZPIPCZHDRMLUUTFVQSP"
}
* Далее необходимо подписать полученную строку "data" электронной цифровой подписью и закодировать в base64.
* Отправить POST запрос на URL https://sandbox.crptech.ru/api/v3/auth/cert/{omsId}
Примечание: omsId является идентификатором соединения, получить его можно на сайте Честного знака. В меню "Управление заказами" выбирается подпункт "Устройства", создаётся новое и копируется свойство "идентификатор соединения"

В headers запроса Content-Type устанавливается на "application/json". в body в формате json отправляется "uuid" из прошлого запроса без изменений и "data", после подписания ЭЦП в кодировке base64.

Примечание: в документации указывается время жизни токена 10 часов. Ссылка на форум с подробностями на 1С: https://infostart.ru/1c/articles/1506206/
* В дальнейшем полученный токен (Пример: "52cd4633-4f18-4580-bb4b-6b1bc45d270d") помещается в Header запроса под ключом "ClientToken". Так же некоторые запросы требуют отсоединенной электронной цифровой подписи в формате base64. Можно подписать пустую строку ЭЦП и положить в заголовок запроса под ключом "X-Signature".

Проверить подключение к api можно GET запросом https://suz.sandbox.crptech.ru/api/v3/ping?omsId=1bcc4b12-92e6-492d-b359-b3650a979888, требует передачи clientToken в заголовке и omsId в строке URL.
## Основные запросы к ГИС МТ
* Создать заказ на эмиссию кодов маркировки (См. пункт 4.4.1).
* Получить статус массива КМ из заказа (См. пункт 4.4.2).
* Получить КМ из заказа (См. пункт 4.4.3).
* Отправить отчёт об использовании КМ (См. пункт 4.4.11).
* Отправить отчёт об агрегации КМ (См. пункт 4.4.10).
* Отправить отчёт о выбытии/отбраковке КМ (См. пункт 4.4.2)
## Основные коды ошибок, возвращаются из модуля интеграции в АРМ Администратора
| error_code | error_description |
| -------- | -------- |
| 1 | Честный знак не отвечает |
| 2 | Честный знак вернул ошибку, {текст ошибки от ЧЗ}, {код ошибки от ЧЗ} |
| 3 | Ошибка в системе ({stacktrace}) |
| 4 | Дата производства задания {дата задания} (номер={id}) не равна текущей дате {текущая дата} |
| 5 | Аварийная остановка производственной линии (номер={id}), причина {причина}|
# Протокол взаимодействия между модулем интеграции и АРМ администратора
## Соглашения
* Все запросы из АРМ в модуль пишутся в очередь с суффиксом _requests
* Все запросы из модуля в АРМ пишутся в очередь с суффиксом _responses
* Если ошибка запроса в ЧЗ, то делаем 3 попытки с таймаутом в 1 сек., пишем ошибку в лог - текущую дату-время в UTC, сообщение и stacktrace ошибки (если есть)
* Если 3 попытки запроса не удались, то пишем соответствующий error_code и error_description
## Создание заказа на эмиссию КМ
### Формат сообщения в очередь create_order_requests:
{"gtin": 04627189191006, "count": 5}
### Формат сообщения в очередь create_order_responses:
{'orderId': 'a-b-c', "gtin": 04627189191006, "count": 5}
## Обновление bufferStatus заказа КМ
### Формат сообщения в очередь update_order_buffer_status_requests:
* orderId
### Формат сообщения в очередь update_order_buffer_status_responses:
[{'orderId': 'a-b-c', 'leftInBuffer': 1, 'totalCodes': 1, 'poolsExhausted': False, 'unavailableCodes': 0, 'availableCodes': 1, 'gtin': '04627189191006', 'bufferStatus': 'ACTIVE', 'totalPassed': 0, 'expiredDate': 1683234003213}]
## Получение массива КМ из заказа
### Формат сообщения в очередь codes_requests:
* orderId, gtin, count
### Формат сообщения в очередь codes_responses:
["codes": ["0104627189191006215CX/Fe 9365o5","0104627189191006215sVYzI 93LH+k"]
## Синхронизация национального каталога
### Формат сообщения в очередь national_catalogue_requests:
* любое сообщение
### Формат сообщения в очередь national_catalogue_responses:
*{
"goods": [
{
"good_id": 226269816,
"gtin": "4627189191006",
"good_name": "Молоко питьевое стерилизованное (для тестирования интеграции)",
"tnved": "0401",
"brand_name": "Test",
"good_status": "published",
"good_detailed_status": [
"published"
],
"updated_date": "2023-04-01 13:20:37"
},
{
"good_id": 229176570,
"gtin": "4627189191020",
"good_name": "Молоко питьевое пастеризованное (для тестирования интеграции)",
"tnved": "0401",
"brand_name": "Test",
"good_status": "published",
"good_detailed_status": [
"published"
],
"updated_date": "2023-04-03 23:20:53"
}
]
}
## Получаем информацию о товаре
**срок годности и полный ТН ВЭД**
### Формат сообщения в очередь product_requests:
* gtin: string
### Формат сообщения в очередь product_responses:
{
gtin: string
expDateValue: string
expDateType: string (ч., сут., нед., мес.)
tnved: string
}
## Синхронизация СУЗ
### Формат сообщения в очередь orders_requests:
* updatedAt (null, если ни разу не обновляли)
### Формат сообщения в очередь orders_responses:
* ordersIds - массив ид заказов КМ
## Полная синхронизация СУЗ
### Формат сообщения в очередь full_oms_sync_requests:
* updatedAt (null, если ни разу не обновляли)
### Формат сообщения в очередь full_oms_sync_responses:
* Массив объектов
[{
"orderId": "123", // ид заказа
"codes": ["a", "b", "c"] // массив кодов
}]
## Отправляем отчёт о нанесении
### Формат сообщения в очередь marking_reports_requests
* codes - массив КМ
* expDate - Дата окончания срока годности продукции (срок хранения более 72 часов).
Допустимые форматы: dd.MM.yyyy / yyMMdd (Пример: 03.04.2023 / 230403)
### Формат сообщения в очередь marking_reports_responses
* reportId - Идентификатор отчёта из ЧЗ, пример "ca71216d-6bc5-4604-8ceb-ed896888abe1"
* codes - массив КМ
* expDate - Дата окончания срока годности продукции (срок хранения более 72 часов).
## Отправляем отчёт о вводе в оборот
### Формат сообщения в очередь turnover_reports_requests
{
"task_id": "task123456", # Идентификатор задания на производство
"participant_inn": "027816074958", # ИНН участника оборота товаров (аккаунт Честного Знака)
"producer_inn": "027816074958", # ИНН производителя
"owner_inn": "027816074958", # ИНН владельца товара
"production_date": "2023-04-21", # дата производства
"products": [ # массив продуктов (каждый код маркировки передается отдельно)
{
"uit_code": "0104627189191020215P<lqR", # код маркировки без криптохвоста (24-значный)
"production_date": "2023-04-21", # дата производства конкретного продукта (делать одинаковой с общей production_date)
"tnved_code": "0401201109", # 10-значный ТН ВЭД код (берется из информации о продукте)
"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111" # GUID ветеринарного сопроводительного сертификата (берется из ФГИС Меркурий)
},
{
"uit_code": "0104627189191020215'V/RO",
"production_date": "2023-04-21",
"tnved_code": "0401201109",
"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"
}
]
}
### Формат сообщения в очередь turnover_reports_responses
{
"reportId": "82da88ec-2984-4837-a658-704dca8921c4",
"owner_inn": "027816074958",
"producer_inn": "027816074958",
"participant_inn": "027816074958",
"production_date": "2023-04-21",
"products":
[
{
"uit_code": "0104627189191020215P<lqR",
"production_date": "2023-04-21",
"tnved_code": "0401201109",
"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"},
{
"uit_code": "0104627189191020215\'V/RO",
"production_date": "2023-04-21",
"tnved_code": "0401201109",
"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"
}
],
}
## Отправляем отчёт об отбраковке
### Формат сообщения в очередь invalidation_reports_requests
* codes - массив КМ
### Формат сообщения в очередь invalidation_reports_responses
* reportId - Идентификатор отчёта из ЧЗ, пример "ca71216d-6bc5-4604-8ceb-ed896888abe1"
* codes - массив КМ
## Обновление статусов отчётов (отчёт о нанесении)
### Формат сообщения в очередь update_report_status_requests
reportId (пример: b8432625-b2fa-4a08-8d09-8779f70fcdf7)
### Формат сообщения в очередь update_report_status_responses
{
"omsId": "9c427558-0d14-4cf4-9a16-b98aedf4cb88",
"reportId": "b8432625-b2fa-4a08-8d09-8779f70fcdf7",
"reportStatus": "FAILED"
}
## Обновление статусов документов (отчёт о вводе в оборот)
### Формат сообщения в очередь update_document_status_requests
{
"document_id": "82da88ec-2984-4837-a658-704dca8921c4"
}
### Формат сообщения в очередь update_document_status_responses
{
"document_id": "82da88ec-2984-4837-a658-704dca8921c4",
"document_status": "CHECKED_NOT_OK",
"downloadDesc": "66: Одно или несколько значений поля \"Идентификатор ВСД\" [1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111] не найдено в базе данных ФГИС \"ВетИС\".",
},
Значение downloadDesc может быть пустым, если при обработке отчёта не будет ошибок при проверке Честным Знаком.
## Отправляем отчёт о балансе
### Формат сообщения в очередь balance_requests
{
"productGroupId": 8
}
P.S.(8 - молочная продукция)
### Формат сообщения в очередь balance_responses
{
"balance": 9760, (в копейках)
"contractId": 1564095,
"organisationId": 11001530518,
"productGroupId": 8
}
# Протокол взаимодействия между модулем диспетчеризации и АРМ оператора
## Запуск задания на нанесение кодов
### Формат сообщения в очередь operation_requests:
* event: "start_line"
* GTIN
* expiredDate: date | null
* taskId - long, номер текущего задания
* plc:
* productSensorAddress (int, адрес датчика продукта)
* redLightAddress (int, адрес красного цвета светофора)
* yellowLightAddress (int, адрес жёлтого цвета светофора)
* greenLightAddress (int, адрес зелёного цвета светофора)
* rejectorAddress (int, адрес отбраковщика)
* emergencyStopAddress (int, адрес аварийного стопа)
* cameraTimeout (int, время задержки до съёмки камеры)
* processTimeout (int, время задержки до обработки)
* rejectTimeout (int, задержка перед отбраковкой)
* rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
* etikerAddress (int, адрес датчика этикеровщика)
* IP* (string)
* port* (int)
* camera:
* IP
* port
* codes: [
{
code,
status
}
]
* rejector:
* invertLogic (bool, инвертирование логики отбраковщика)
### Формат сообщения в очередь operation_responses:
**Пока не используем**
* event: "start_line"
## Остановка заданий
### Формат сообщения в очередь operation_requests
* event: "stop_line"
* plc:
* productSensorAddress (int, адрес датчика продукта)
* redLightAddress (int, адрес красного цвета светофора)
* yellowLightAddress (int, адрес жёлтого цвета светофора)
* greenLightAddress (int, адрес зелёного цвета светофора)
* rejectorAddress (int, адрес отбраковщика)
* emergencyStopAddress (int, адрес аварийного стопа)
* cameraTimeout (int, время задержки до съёмки камеры)
* processTimeout (int, время задержки до обработки)
* rejectTimeout (int, задержка перед отбраковкой)
* rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
* etikerAddress (int, адрес датчика этикеровщика)
* IP* (string)
* port* (int)
### Формат сообщения в очередь operation_responses
**Пока не используем**
* event: "stop_line"
* updatedAt: datetime (дата-время остановки)
* ok: bool
* error_code: int | null
* error_description: string | null
## Остановка заданий
### Формат сообщения в очередь operation_responses
event: "emergency_stop_line"
## Валидация
### Формат сообщения в очередь validate_codes_responses
* rejected: bool
* code: bytea | null
* updatedAt: datetime
* cause: enum (string)
* taskId: long
## Возвращаем коды в режиме отладки
### Формат сообщения в очередь debug_codes_responses
* code: bytea | null
* updatedAt: datetime
## Наладка
### Формат сообщения в очередь operation_requests
event: "debug"
### Формат сообщения в очередь operation_responses
**Пока не используем**
* event: "debug"
* updatedAt: datetime (дата-время наладки)
* ok: bool
* error_code: int | null
* error_description: string | null
# Структура базы данных
## Соглашения
* с помощью * отмечены обязательные поля
* название БД - milk_factory_db
## Task Задание:
* productLine - внешний ключ на ProductionLine
* product - внешний ключ на Product
* number* - уникальный номер
* mcCount - кол-во КМ (в коробе)
* createdAt - дата-время создания задания (заполняется автоматически)
* startedAt - дата-время фактического начала выполнения задания
* finishedAt - дата-время фактического окончания выполнения задания
* duration - продолжительность выполнения задания, в сек.
* veterinaryAccompanyingDocument - ветеринарный сопроводительный документ, ВСД
* status - enum:
* New (Новая, по умолчанию)
* Started (В работе)
* Finished (Закрыта)
* productionDate* - дата производства
* packingDate* - дата упаковки (дата нанесения)
* planCount - плановое количество
* factCount - фактическое количество
## Order (Заказ)
* gtin (string)
* count (long)
* createAt (date)
* bufferStatus CREATED("Создан"),
PENDING("Обрабатывается"),
ACTIVE("Создан"),
EXHAUSTED("Закончились коды"),
REJECTED("Не доступен"),
CLOSED("Закрыт")
* serviceProvider - (many to one) связь с сервис-провайдером
* expiredDate - дата окончания срока годности кодов маркировки
## Product (Продукт)
* brand (товарный знак)
* category (многие к 1 на Category)
* GTIN (например, 04675093352013, уникален)
* threshold count (пороговое значение)
* mcResiduals (остаток КМ)
* name (название)
* expDateValue (string, продолжительность жизни продукта)
* expDateType (enum string, единица измерения продолжительности жизни продукта)
* HOUR (ч. в интеграторе)
* DAY (сут. в интеграторе)
* WEEK (нед. в интеграторе)
* MONTH (мес. в интеграторе)
## Category
* title* (подкатегория, пока строка “молоко в первичных упаковках нетто-объемом не более 0,35 л, для детского питания”)
* description
* tnved* (ТНВЭД, например, 0401201101)
## Отчёт Report (отчёт о нанесении)
* reportId* (получаем с ЧЗ)
* createdAt* (datetime)
* task* (many to one на Task)
* status* (CREATED (наш статус), DRAFT, PENDING, READY_TO_SEND, REJECTED, SENT, CHECK, SUCCESS, FAILED, PARTIALLY)

## Документ Document (отчёт о вводе в оборот)
* documentId* (получаем с ЧЗ)
* createdAt* (datetime)
* task* (many to one на Task)
* status* (CREATED (наш статус), IN_PROGRESS, CHECKED_OK, CHECKED_NOT_OK, PROCESSING_ERROR, PARSE_ERROR, WAIT_FOR_CONTINUATION)

## ProductionLine
см. https://github.com/energovision/milk-factory-admin/tree/main/common-jpa/src/main/java/com/energovision/entity
## MarkingCode (Коды маркировки)
* order - many to one на Order
* task - many to one на Task
* report - many to one на Report
* document - many to one на Report
* code - массив байт
* status* (Emitted (Получен), Ready_for_production (Добавлен в задание на производство), Printing (Отправлен на печать), Approved (Отсканирован), Expired (Просрочен), Invalid (Отбракован), Valid (Валиден), Marked (Отправлен в отчёт о нанесении), Turnovered (Введён в оборот)), см. https://hackmd.io/NUbsjS2CSSaE8YX9iiwKdQ?view#Диаграмма-состояний-КМ
* createdAt (datetime, автоматически заполняем по текущей дате-времени)
* ...
## DebugMarkingCode (Коды маркировки в режиме отладки)
**нужны только для того, чтобы их выводить в режиме реального времени**
* code - массив байт
* updatedAt - datetime
## ServiceProvider (Сервис провайдер)
* UUID - String(36)
## Камера Camera
* IP*
* port*
## Programmable Logic Controller (программируемый логический контроллер)
* productSensorAddress (int, адрес датчика продукта)
* redLightAddress (int, адрес красного цвета светофора)
* yellowLightAddress (int, адрес жёлтого цвета светофора)
* greenLightAddress (int, адрес зелёного цвета светофора)
* rejectorAddress (int, адрес отбраковщика)
* emergencyStopAddress (int, адрес аварийного стопа)
* cameraTimeout (int, время задержки до съёмки камеры)
* processTimeout (int, время задержки до обработки)
* rejectTimeout (int, задержка перед отбраковкой)
* rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
* IP* (string)
* port* (int)
* productionLine (1 к 1, производственная линия)
## Reject (Брак)
* code* - многие к одному к сущности MarkingCode
* cause* - enum (string, причина отбраковки)
* GTIN (некорректный GTIN)
* Doubling (дублирование)
* NotRead (не считан)
* Expired (просрочен)
* createdAt* (когда создан, заполняется автоматически)
## Соответствие статусов КМ и типов отчётов
| Статус КМ | Тип отчёта |
| -------- | -------- |
| Введён в оборот | Ввод в оборот |
| Нанесён | Нанесение |
| Недействителен | Отбраковка |
## Конфиг АРМ оператора
* productionLine
* id (ид производственной линии)
* plc
* productSensorAddress (int, адрес датчика продукта)
* redLightAddress (int, адрес красного цвета светофора)
* yellowLightAddress (int, адрес жёлтого цвета светофора)
* greenLightAddress (int, адрес зелёного цвета светофора)
* rejectorAddress (int, адрес отбраковщика)
* emergencyStopAddress (int, адрес аварийного стопа)
* etikerAddress (int, адрес датчика этикеровщика)
* IP (string)
* port (int)
* camera
* IP
* port
* rejector:
* invertLogic (bool, инвертирование логики отбраковщика)