OGC API — Features и Processes

> Кратко. /api/ogc отдаёт слои сети по стандарту OGC API — Features (GeoJSON в WGS 84): участки, узлы, потребители, источники, задвижки. Там же — OGC API — Processes: трассировка, локализация аварии, выборки, статистика и гидравлический расчёт. Так слои ТГИД подключают QGIS, GDAL и ГИС акиматов без GeoServer.

Читаю как

Адреса

Адрес Что
GET /api/ogc стартовая страница: ссылки conformance, data, processes, service-desc (/openapi.json)
GET /api/ogc/conformance классы стандарта: Features часть 1 (core, geojson, oas30), часть 4 (запись, ETag), Processes часть 1
GET /api/ogc/collections пять коллекций с охватом сети
GET /api/ogc/collections/{id} одна коллекция
GET /api/ogc/collections/{id}/items объекты: GeoJSON FeatureCollection (application/geo+json)
GET /api/ogc/collections/{id}/items/{fid} один объект с ETag (для записи)

Вход — как у API v1: Authorization: Bearer <токен входа>, роль не ниже «Просмотр». Ключи ArcGIS, MCP и API v2 здесь не действуют.

Коллекции

id Объекты Свойства (кроме fileid — фрагмент)
pipes живые участки основной схемы с геометрией (без участков внутренних схем) name, node_start, node_end, sign, diameter_mm, diameter_internal_mm, length_m, state_supply, state_return (из первого паспорта трубы)
nodes узлы основной схемы (без узлов внутренних схем) name, node_type
consumers реальные и обобщённые потребители в точке узла name, kind (real, generalized), source_id, node_id, load_gcal_h
heat_sources источники тепла name, node_id
valves задвижки в середине участка name, line_id, diameter_mm, state (1 открыта, 2 закрыта)

Что учесть:

  • Участков и узлов внутренних схем (камер, ЦТП) в коллекциях нет — как в выборке по условиям, FeatureServer и встраиваемой карте. Во фрагменте 74 копии Алматы pipes отдаёт 3625 участков (ещё 196 — внутренние схемы).
  • Свойства участка берутся из первого по номеру паспорта трубы, а выборка по условиям — из самого длинного. На участках с несколькими паспортами Ду может различаться; во фрагменте 74 обе дают 2068 участков Ду ≥ 500.
  • Реальные и обобщённые потребители лежат в разных таблицах, и номера в них повторяются. Поэтому id обобщённого потребителя в коллекции сдвинут на 1 000 000 000 (id 5 в таблице обобщённых — объект 1000000005), а номер в его таблице — в свойстве source_id. id в коллекции уникален, /items/{fid} возвращает ровно один объект.

Объекты: items

Параметр Что
limit 1…10 000, по умолчанию 100
offset сдвиг; следующая страница — ссылка rel: next (есть, пока страница полная), предыдущая — prev
bbox minLon,minLat,maxLon,maxLat в CRS84 (долгота, широта); объект попадает, если его рамка пересекает bbox
fileid фрагмент

Системы координат: геометрия — всегда WGS 84 в порядке «долгота, широта» (CRS84), 7 знаков после запятой; охват коллекций — тоже CRS84. Параметра crs нет. В базе сеть хранится в своей системе города: API пересчитывает геометрию сам и переводит bbox в систему сети. Неверный bbox (не четыре числа, min > max, широта за ±90) — 400. Общего числа объектов (numberMatched) в ответе нет — только numberReturned.

Пример — участки в рамке в центре Алматы (копия Алматы):

curl -s "$API/api/ogc/collections/pipes/items?bbox=76.93,43.24,76.95,43.25&limit=3" -H "Authorization: Bearer $TOKEN"
{"type":"FeatureCollection","numberReturned":3,"features":[
  {"type":"Feature","id":993,"geometry":{"type":"LineString","coordinates":[[76.9367993,43.2507663],[76.9369258,43.2499472]]},
   "properties":{"fileid":1,"name":null,"node_start":324,"node_end":330,"sign":1,"diameter_mm":800.0,
                 "diameter_internal_mm":806.0,"length_m":91.6,"state_supply":1,"state_return":1}}, "…"],
 "links":[{"href":".../items?bbox=76.93%2C43.24%2C76.95%2C43.25&limit=3&offset=0","rel":"self","type":"application/geo+json"},
          {"href":".../items?bbox=76.93%2C43.24%2C76.95%2C43.25&limit=3&offset=3","rel":"next","type":"application/geo+json"}]}

Сверка на копии Алматы: в этой рамке 2041 участок — столько же насчитали OGC (limit=10000), FeatureServer (returnCountOnly с geometry) и GDAL (ogrinfo -spat). Во фрагменте 74 у OGC и FeatureServer одинаково: 3821 участок, 1777 узлов, 1037 потребителей, 2 источника, 35 задвижек.

QGIS и GDAL

QGIS: «Слой → Добавить слой → Добавить слой WFS / OGC API — Features» → «Создать», адрес <API>/api/ogc, версия «OGC API — Features». Вход — проверка подлинности «API Header»: заголовок Authorization, значение Bearer <токен>. Токен входа живёт 8 часов; для постоянного подключения удобнее FeatureServer с ключом на 90 дней.

GDAL (драйвер OAPIF). Выполнено на стенде копии Алматы, GDAL 3.9.2:

ogrinfo -ro -so "OAPIF:http://127.0.0.1:8090/api/ogc"
# 1: pipes (title: Участки теплосети) (Line String)
# 2: nodes (title: Узлы сети) (Point)
# 3: consumers (title: Потребители) (Point)
# 4: heat_sources (title: Источники тепла) (Point)
# 5: valves (title: Задвижки) (Point)
ogrinfo -ro -so -spat 76.93 43.24 76.95 43.25 "OAPIF:http://127.0.0.1:8090/api/ogc" pipes
# Feature Count: 2041
# Supported SRS: OGC:CRS84

С включённым входом токен передаётся настройкой GDAL GDAL_HTTP_HEADERS="Authorization: Bearer <токен>" (на стенде без входа этот вариант не проверялся).

Запись (часть 4)

POST /collections/{id}/items, PUT и PATCH /items/{fid} (JSON Merge Patch), DELETE /items/{fid} — узлы, участки, задвижки и источники; потребители — только чтение. Правка идёт теми же операциями, что в окне редактора: права вида объекта, журнал отмены, audit_log, проверка связности. Версия — ETag из GET …/items/{fid}, If-Match с устаревшей версией — 412. Нужны MUTATIONS_ENABLED, для геометрии, создания и удаления — TOPOLOGY_MUTATIONS_ENABLED. Подробно — docs/ogc-api.md в репозитории API.

Процессы

Адрес Что
GET /api/ogc/processes девять процессов
GET /api/ogc/processes/{id} описание: входы (JSON Schema без $ref) и выход result
POST /api/ogc/processes/{id}/execution {"inputs": {…}, "response": "raw" | "document"}
GET /api/ogc/jobs/{jobId}, …/results состояние и результат задания (только heat-hydraulic)
Процесс Инструмент MCP Запуск
network-trace network_trace синхронно
valve-isolation valve_isolation синхронно
network-select select_network синхронно
network-statistics network_statistics синхронно
regime-analysis regime_analysis синхронно
thematic-summary thematic_summary синхронно
wear-priorities wear_priorities синхронно
data-quality data_quality синхронно
heat-hydraulic run_calculation задание Celery: 201 и Location на /jobs/{id}

Входы, права и ограничения частоты — те же, что у инструментов MCP. heat-hydraulic — настоящий расчёт (право «Запуск расчётов», результаты пишутся в базу).

Пример — длина сети фрагмента 74 (копия Алматы):

curl -s -X POST "$API/api/ogc/processes/network-statistics/execution" -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" -d '{"inputs":{"query":"length","fragment_ids":[74]},"response":"document"}'
# {"result":{"query":"length","title":"Длина теплопроводов, м","fragment_ids":[74],
#            "length_supply_m":197263.2,"length_return_m":197576.4,"length_total_m":394839.6}}

Выборка участков Ду ≥ 500 во фрагменте 74 (network-select, {"target":"lines","conditions":[{"field":"diameter", "op":"ge","value":500}],"fragment_ids":[74],"limit":1}) вернула total: 2068, total_length_m: 245608.8 за 0,16 с.

Ошибки — RFC 7807 (application/problem+json): no-such-process (404), invalid-parameter-value (400 — неверные входы), result-not-ready (404), no-such-job (404); 5xx — без подробностей. Состояние задания (GET /api/ogc/jobs/{jobId}) берётся из того же источника, что GET /api/v1/task/{task_id}. API нескольких городов помнит город каждого задания: неизвестный или чужой номер — 404 no-such-job. API одного города спрашивает Celery, а тот не отличает неизвестное задание от ещё не начатого — ответ accepted.

Для разработчика

  • API: routers/ogc.py (Features, ссылки от адреса запроса и API_PUBLIC_PREFIX), database/ogc_features.py (COLLECTIONS, MAX_LIMIT, parse_bbox), routers/ogc_write.py и database/ogc_transactions.py (запись), routers/ogc_processes.py (PROCESSES). Те же коллекции — у FeatureServer и встраиваемой карты.
  • Тесты: API — tests/test_ogc_features.py, tests/test_ogc_write.py, tests/test_ogc_processes.py (в том числе test_jobs_status_without_stub — состояние задания без подмены); e2e — e2e/functions/developer-api.spec.ts (OGC против FeatureServer, рамка, ошибки, процессы).
Хотите увидеть эту функцию на своих данных?Покажем ТГИД на демонстрации и ответим на вопросы инженеров.
Запросить демо