{"openapi":"3.1.0","info":{"title":"OPC UA SendBox API","description":"REST API OPC UA SendBox - публичной песочницы OPC UA серверов. Контракт версионированный: /api/v1/... (пути /api/... работают как совместимый алиас). Получите ключ через POST /api/v1/keys, создайте личный сервер через POST /api/v1/sessions и подключите к выданному endpoint свой клиент: UaExpert, SCADA, ModbusToolkit. Общий демо-сервер работает всегда, его адрес отдаёт GET /api/v1/shared, возможности — GET /api/v1/capabilities.","version":"0.1.0"},"paths":{"/api/v1/keys":{"post":{"tags":["Ключи"],"summary":"Issue Key","description":"Выдать API-ключ без регистрации. Ключ живёт в памяти сервиса.","operationId":"issue_key_api_v1_keys_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyOut"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}}}},"/api/v1/sessions":{"post":{"tags":["Сессии"],"summary":"Create Session","description":"Создать личный OPC UA сервер. Без тела — демо-набор тегов и алармов.","operationId":"create_session_api_v1_sessions_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SessionCreate"},{"type":"null"}],"title":"Body"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}},"get":{"tags":["Сессии"],"summary":"List Sessions","description":"Сессии этого ключа.","operationId":"list_sessions_api_v1_sessions_get","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionOut"},"title":"Response List Sessions Api V1 Sessions Get"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}":{"get":{"tags":["Сессии"],"summary":"Get Session","description":"Сессия с тегами, алармами и текущими значениями.","operationId":"get_session_api_v1_sessions__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDetailOut"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}},"delete":{"tags":["Сессии"],"summary":"Delete Session","description":"Остановить сервер сессии и освободить порт.","operationId":"delete_session_api_v1_sessions__session_id__delete","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"responses":{"204":{"description":"Successful Response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}/tags":{"post":{"tags":["Теги"],"summary":"Add Tag","description":"Добавить тег: узел `ns=2;s=Tags.<name>` появится сразу.","operationId":"add_tag_api_v1_sessions__session_id__tags_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagSpec"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagSpec"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}/tags/{name}":{"delete":{"tags":["Теги"],"summary":"Remove Tag","description":"Удалить тег (сначала удалите алармы, которые на него ссылаются).","operationId":"remove_tag_api_v1_sessions__session_id__tags__name__delete","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"responses":{"204":{"description":"Successful Response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}/alarms":{"post":{"tags":["Алармы"],"summary":"Add Alarm","description":"Добавить аларм: limit по порогу тега, periodic по таймеру или manual.","operationId":"add_alarm_api_v1_sessions__session_id__alarms_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmSpec"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmSpec"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}/alarms/{name}":{"delete":{"tags":["Алармы"],"summary":"Remove Alarm","description":"Удалить аларм; активный перед удалением сбрасывается событием.","operationId":"remove_alarm_api_v1_sessions__session_id__alarms__name__delete","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"responses":{"204":{"description":"Successful Response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/sessions/{session_id}/alarms/{name}/trigger":{"post":{"tags":["Алармы"],"summary":"Trigger Alarm","description":"Активировать, сбросить или переключить аларм вручную — для проверки реакции SCADA.","operationId":"trigger_alarm_api_v1_sessions__session_id__alarms__name__trigger_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ключ из POST /api/keys","title":"X-Api-Key"},"description":"Ключ из POST /api/keys"}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AlarmTrigger"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmStateOut"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}},"description":"Service Unavailable"}}}},"/api/v1/shared":{"get":{"tags":["Общий сервер"],"summary":"Shared Info","description":"Постоянный общий демо-сервер: ключ не нужен, только чтение.","operationId":"shared_info_api_v1_shared_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedOut"}}}}}}},"/api/v1/capabilities":{"get":{"tags":["Служебное"],"summary":"Capabilities","description":"Версия сервиса, поддерживаемые возможности и лимиты — чтобы клиент деградировал честно (ADR-003).","operationId":"capabilities_api_v1_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesOut"}}}}}}},"/api/v1/stats":{"get":{"tags":["Служебное"],"summary":"Stats","description":"Счётчики сервера: OPC UA клиенты, HTTP-запросы и ошибки, uptime.","operationId":"stats_api_v1_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsOut"}}}}}}},"/healthz":{"get":{"tags":["Служебное"],"summary":"Healthz","description":"Здоровье: 200, если общий сервер работает, иначе 503.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOut"}}}}}}},"/metrics":{"get":{"tags":["Служебное"],"summary":"Metrics","description":"Метрики Prometheus: сессии, порты, клиенты, общий сервер, дропы телеметрии, HTTP.","operationId":"metrics_metrics_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"AlarmSpec":{"properties":{"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]{0,63}$","title":"Name"},"kind":{"type":"string","enum":["limit","periodic","manual"],"title":"Kind","default":"limit"},"tag":{"anyOf":[{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]{0,63}$"},{"type":"null"}],"title":"Tag"},"high":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"High"},"low":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Low"},"deadband":{"type":"number","minimum":0.0,"title":"Deadband","default":0.0},"period_s":{"type":"number","maximum":3600.0,"minimum":1.0,"title":"Period S","default":10.0},"severity":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Severity","default":700},"message":{"type":"string","maxLength":200,"title":"Message","default":""}},"additionalProperties":false,"type":"object","required":["name"],"title":"AlarmSpec","description":"Аларм сессии: условие `ns=2;s=Alarms.<name>` (ADR-002 п. 3b).\n\n- `limit` — по порогу тега: активен при значении > high или < low, сброс с\n  гистерезисом `deadband`;\n- `periodic` — каждые `period_s` переключается активен/норма;\n- `manual` — только по команде trigger."},"AlarmStateOut":{"properties":{"alarm":{"type":"string","title":"Alarm"},"active":{"type":"boolean","title":"Active"}},"type":"object","required":["alarm","active"],"title":"AlarmStateOut"},"AlarmTrigger":{"properties":{"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active","description":"true/false — задать, null — переключить"}},"type":"object","title":"AlarmTrigger"},"CapabilitiesOut":{"properties":{"service":{"type":"string","title":"Service","description":"Имя сервиса"},"version":{"type":"string","title":"Version","description":"Версия сервиса, SemVer"},"api_version":{"type":"integer","title":"Api Version","description":"Версия контракта REST API; путь /api/v{N}/..."},"features":{"items":{"type":"string"},"type":"array","title":"Features","description":"Поддерживаемые возможности; отсутствие в списке = не поддерживается"},"limits":{"additionalProperties":{"type":"integer"},"type":"object","title":"Limits","description":"Лимиты песочницы (сессии, теги, алармы, таймауты)"}},"type":"object","required":["service","version","api_version","features","limits"],"title":"CapabilitiesOut","description":"Возможности сервиса для честной деградации клиентов (TASK-204, ADR-003)."},"ErrorOut":{"properties":{"detail":{"type":"string","title":"Detail","description":"Что пошло не так, по-русски"}},"type":"object","required":["detail"],"title":"ErrorOut"},"HealthOut":{"properties":{"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"shared":{"type":"string","title":"Shared"},"sessions":{"type":"integer","title":"Sessions"},"ports_free":{"type":"integer","title":"Ports Free"}},"type":"object","required":["status","version","shared","sessions","ports_free"],"title":"HealthOut"},"KeyOut":{"properties":{"key":{"type":"string","title":"Key","description":"API-ключ: передавайте в заголовке X-API-Key"}},"type":"object","required":["key"],"title":"KeyOut"},"SessionCreate":{"properties":{"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/TagSpec"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Теги; null — демо-набор"},"alarms":{"anyOf":[{"items":{"$ref":"#/components/schemas/AlarmSpec"},"type":"array"},{"type":"null"}],"title":"Alarms","description":"Алармы; null — демо-набор"}},"type":"object","title":"SessionCreate","description":"Тело POST /api/sessions. Без полей — демо-набор тегов и алармов."},"SessionDetailOut":{"properties":{"id":{"type":"string","title":"Id"},"state":{"type":"string","title":"State","description":"starting | running | stopping"},"endpoint_url":{"type":"string","title":"Endpoint Url","description":"Адрес для OPC UA клиента"},"port":{"type":"integer","title":"Port"},"web_ui_url":{"type":"string","title":"Web Ui Url","description":"Страница сессии в веб-интерфейсе"},"created_at":{"type":"string","title":"Created At","description":"Время создания, ISO 8601 UTC"},"expires_at":{"type":"string","title":"Expires At","description":"Когда сессию закроет потолок жизни, ISO 8601 UTC"},"idle_closes_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idle Closes At","description":"Когда сессию закроет простой; null — пока подключены OPC UA клиенты"},"clients":{"type":"integer","title":"Clients","description":"Подключённые OPC UA сессии"},"tags":{"items":{"$ref":"#/components/schemas/TagSpec"},"type":"array","title":"Tags"},"alarms":{"items":{"$ref":"#/components/schemas/AlarmSpec"},"type":"array","title":"Alarms"},"values":{"additionalProperties":true,"type":"object","title":"Values","description":"Текущие значения тегов"},"alarm_states":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Alarm States","description":"Активен ли каждый аларм"}},"type":"object","required":["id","state","endpoint_url","port","web_ui_url","created_at","expires_at","idle_closes_at","clients","tags","alarms","values","alarm_states"],"title":"SessionDetailOut"},"SessionOut":{"properties":{"id":{"type":"string","title":"Id"},"state":{"type":"string","title":"State","description":"starting | running | stopping"},"endpoint_url":{"type":"string","title":"Endpoint Url","description":"Адрес для OPC UA клиента"},"port":{"type":"integer","title":"Port"},"web_ui_url":{"type":"string","title":"Web Ui Url","description":"Страница сессии в веб-интерфейсе"},"created_at":{"type":"string","title":"Created At","description":"Время создания, ISO 8601 UTC"},"expires_at":{"type":"string","title":"Expires At","description":"Когда сессию закроет потолок жизни, ISO 8601 UTC"},"idle_closes_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idle Closes At","description":"Когда сессию закроет простой; null — пока подключены OPC UA клиенты"},"clients":{"type":"integer","title":"Clients","description":"Подключённые OPC UA сессии"}},"type":"object","required":["id","state","endpoint_url","port","web_ui_url","created_at","expires_at","idle_closes_at","clients"],"title":"SessionOut"},"SharedOut":{"properties":{"endpoint_url":{"type":"string","title":"Endpoint Url"},"status":{"type":"string","title":"Status","description":"running | restarting | down"},"restarts":{"type":"integer","title":"Restarts"},"read_only":{"type":"boolean","title":"Read Only","default":true}},"type":"object","required":["endpoint_url","status","restarts"],"title":"SharedOut"},"StatsOut":{"properties":{"clients":{"type":"integer","title":"Clients","description":"OPC UA клиенты общего сервера и личных сессий"},"requests_per_s":{"type":"number","title":"Requests Per S","description":"HTTP-запросы в секунду за окно 5 с"},"errors_per_s":{"type":"number","title":"Errors Per S","description":"Ответы со статусом 400+ в секунду за окно 5 с"},"requests_total":{"type":"integer","title":"Requests Total","description":"Всего HTTP-запросов с запуска"},"errors_total":{"type":"integer","title":"Errors Total","description":"Всего ответов со статусом 400+ с запуска"},"uptime_s":{"type":"number","title":"Uptime S","description":"Время работы сервиса, с"}},"type":"object","required":["clients","requests_per_s","errors_per_s","requests_total","errors_total","uptime_s"],"title":"StatsOut","description":"Счётчики сервера для UI (TASK-205)."},"TagSpec":{"properties":{"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9_]{0,63}$","title":"Name"},"data_type":{"type":"string","enum":["Double","Float","Int16","Int32","UInt16","UInt32","Boolean"],"title":"Data Type","default":"Double"},"kind":{"type":"string","enum":["counter","sawtooth","triangle","meander","sine","random_uniform","random_walk","ramp_oneshot","countdown","step","profile","toggle","pwm","random_bit","counter_bits","constant"],"title":"Kind","default":"sine"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"update_period_s":{"type":"number","maximum":60.0,"minimum":0.1,"title":"Update Period S","default":1.0},"writable":{"type":"boolean","title":"Writable","default":false},"historize":{"type":"boolean","title":"Historize","default":true},"description":{"type":"string","maxLength":200,"title":"Description","default":""}},"additionalProperties":false,"type":"object","required":["name"],"title":"TagSpec","description":"Тег сессии: переменная `ns=2;s=Tags.<name>` со своим генератором."}}},"tags":[{"name":"Ключи","description":"API-ключ без регистрации."},{"name":"Сессии","description":"Личные OPC UA серверы."},{"name":"Теги","description":"Переменные с генераторами значений."},{"name":"Алармы","description":"События Alarms & Conditions."},{"name":"Общий сервер","description":"Постоянный демо-сервер только для чтения."},{"name":"Служебное","description":"Здоровье процесса."}]}