Практика реализации Веб-ГИС приложений и сервисов на основе открытых ресурсов. Начало

в 12:16, , рубрики: bash, django, drf, postgis, postgresql

Идея спасти мир и при этом заработать немного шекелей витала у меня в голове уже давно. Имея неплохой накопленный опыт в области геоинформационных систем и защитивши в свое время диссертацию с их применением мне не хватало знаний разработчика. Окончив IT-курсы и получив доступ к «Святому Граалю знаний» я понял, – пора, и завертелось!

Летом 2024 года мы в составе команды «Arrow» одержали победу, заняв третье место в хакатоне «Лидеры цифровой трансформации» и вошли с нашим проектом в топ-100, став резидентами «Академии инноваторов» у нас появился свой стартапп.

Общая идея такова. Arrow - это платформа для анализа и обработки спутниковых снимков, использующая технологии машинного обучения и нейросетей для мониторинга окружающей среды, строительства и природопользования. Наш продукт помогает бизнесу и государственным структурам автоматизировать выявление экологических нарушений и незаконных построек, обеспечивая более точное и своевременное реагирование. Это в «розовом» будущем, а пока это только проект «Мобильное приложение для управления антропогенной нагрузкой на особо охраняемых природных территориях Камчатского края», занявшее призовое место, хотя и этот результат тоже когда-то был только в мечтах.

Я хочу открыть целый цикл статей в котором постараюсь осветить историю жизненного цикла нашего проекта «Arrow», которая будет писаться на ваших глазах. Здесь будет все: и фронт и бэк и мобильная разработка, будет и деплой в облако. В этих статьях, которые к стати буду писать не только я, но и ребята с моей команды, мы хотим осветить все начиная от создания MVP (минимально жизнеспособный продукт) и заканчивая выводом проекта в продакшн, анализ целевой аудитории и поиск первых клиентов, привлечение первых инвестиций, подбор команды, в общем все этапы через которые нам предстоит пройти для достижения своей цели, - получения интересного и востребованного продукта. Начнем же…

В современных реалиях блокировки доступа ко многим программным продуктам остро встает вопрос о переходе к использованию отечественных или, замещающих их и распространяемых открыто, ресурсам для построения элементов инфраструктуры пространственных данных.

Данная статья освещает практический подход для решения задачи построения Веб-ГИС приложения и сервисов на основе открытых ресурсов и на примере нашего проекта. Основное внимание в ней будет уделено созданию общей структуры проекта и освещению ресурсов на которых он функционирует.

Проект реализован с применением клиент-серверной архитектуры (рисунок 1). Серверная часть включает в себя СУБД для хранения векторных и растровых наборов данных, файловое хранилище растровых тайлов, сервер приложений Gunicorn, обслуживающий сам проект, и веб-сервер Nginx для взаимодействия, через протокол REST full с сервисами приложения, программ клиентов, которыми могут быть десктопные и (или) мобильные и (или) веб-браузеры. Таким образом, весь проект будет размещен в облаке Reg.ru о чем в дальнейшем будет отдельная статья, а пока мы работаем на нашей локальной машине (localhost), с организацией туннелированного доступа с применением Ngrok.

Рисунок – 1. Архитектура проекта

Рисунок – 1. Архитектура проекта

Технологический стек проекта включает в себя следующие свободно распространяемые ресурсы:

  • СУБД Postgresql с надстройкой PostGIS, которая предоставляет дополнительные возможности для работы с геопространственными данными, превращая базу данных в геореляционную;

  • Широко распространенный скриптовый язык программирования Python;

  • Не менее широко известный фреймворк, предназначенный для создания веб-приложений Django, взаимодействующий с СУБД с помощью технологии ORM (Object Relations Mapping). Эта технология позволяет работать с выбранной СУБД посредствам классов языка программирования, меняя лишь специальный драйвер, минуя при этом необходимость в написании SQL-запросов и, что самое главное, без изменения исходного программного кода приложения;

  •  Для взаимодействия клиента с серверной частью предназначен Django REST фреймворк. DRF – одна из современных технологий создания API (программного интерфейса приложения), основным преимуществом которой является возможность организации совместной работы клиентских и серверных программ, написанных на различных языках программирования;

  • Библиотека GDAL содержит в себе полноценный функционал современных ГИС (геоинформационных систем) общего назначения, объединяя в себе две библиотеки – одноименную gdal, для работы с растровыми наборами данных и ogr, для работы с векторными форматами данных (shape, kml, geojson и др.). Активация этой библиотеки превращает фреймворк Django в GeoDjango;

  • - Для анализа спутниковых снимков (получаемых через API  Sentinel Hub) применяются библиотеки Numpy и Pandas, дополнительно используется Jupiter Notebook, в том числе для работы со сверточной нейронной сетью      U-Net для сегментации изображений; 

  • Библиотека Leaflet (либо OpenLayer 3) посредствам java-скриптов и во взаимодействии с html-шаблонами и таблицами стилей CSS, визуализирует геоданные в окне веб-браузера и предоставляет пользователю элементы интерфейса для работы с серверным приложением;

  • В качестве карты-подложки применяется OSM-карта.

Создание проекта предполагает установку языка программирования, модуля для работы с виртуальными средами venv, пакетного менеджера pip, СУБД Postgrsql с расширением PostGIS, в качестве редактора кода я использую VSCode. В зависимости от операционной системы для установки всего этого добра используются различные менеджеры, например в MacOS это brew, в Ubuntu – apt, в Mandjaro pacman и т.д. Я работаю еще в Windows, но там использую стандартные .exe-шники. Тут и далее буду работать с Ubuntu, так как в дальнейшем при деплое на удаленном сервере Reg.ru тоже будет применяться этот дистрибутив Linux.

sudo apt install python3-venv python3-pip postgresql postgis

Далее создается база данных от имени пользователя postgres. Переключаемся на этого пользователя и заходим в утилиту psql.

sudo su postgres
psql
ALTER USER postgres WITH PASSWORD `admin`;

Теперь создаем базу данных.

CREATE DATABASE test;

Далее нужно активировать для этой базы данных расширение postgis. Подключаемся к базе.

c test

И активируем расширение.

CREATE EXTENSION postgis;

Со списком всех доступных расширений для работы с пространственными данными и для их активации рекомендую ознакомится со справкой на сайте PostGIS.

Выходим.

q

Переключаемся с пользователя «postgres» на пользователя операционной системы.

exit

Теперь при создании полей в моделях базы данных нам, помимо стандартных типов данных, также будет доступно поля данных с типом «геометрия».

Следующим шагом нам необходимо создать виртуальное окружение для размещения в нем нашего проекта и установить в него необходимые зависимости, главные из которых фреймворки django и djangorest, а также драйвер для работы с базой данных Postgresql – psycopg2-binary.

mkdir geodjango

Переключаемся на эту папку, это будет наша рабочая директория.Создаем папку для размещения проекта.

cd geodjango 

Создаем окружение, где env – это названия окружения.

python –m venv env

И активируем его (для выхода из виртуального окружения необходимо запустить файл deactivate).

source env/bin/activate

Теперь установим в виртуальное окружение необходимые для работы проекта зависимости. Список этих зависимостей содержится в файле requirements.txt.

pip install –r requirements.txt

Можно проверить все ли необходимые зависимости установлены командой pip freeze (с их версиями). 

Находясь в рабочей директории «geodjango», приступаем к созданию проекта и приложения в нем.

Создание проекта выполняется командой, где geodjango – это название проекта.

django-admin startproject geodjango

Создание приложения выполняется командой, где geoapp  – это названия приложения.

python manage.py startapp geoapp

При создании проекта и приложения в нем с помощью фреймворка Django формируется первоначальная файловая структура. Каждый из этих файлов имеет свое строгое предназначение. Например, файл settings.py, в том числе, предназначен для подключения к предварительно созданной на основе шаблона PostGIS базе данных.

Для настройки подключения используется секция DATABASES.

DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'NAME': 'test',
        'USER': 'postgres',
        'PASSWORD': 'admin',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

Структура базы данных создается в файле models.py, где указываются необходимые модели (таблицы) с атрибутивными полями, хранящими данные определенных типов, а также поле для хранения геометрии пространственных объектов.

После создания моделей выполняется их миграция в базу данных и регистрация в файле admin.py для доступа к данным через специальную административную панель.

Каждое внесение изменений в модели базы данных требует создание миграций.

python manage.py makemigrations

Команда ниже создает модели в базе данных.

python manage.py migrate

Для взаимодействия с данными базы предназначен файл views.py. Он содержит функции и классы представлений, описывающих программную логику приложения.

Настройка взаимодействия клиента с этими представлениями осуществляется в результате процедуры роутинга – задания url-адресов доступа к тем или иным функциям, выполняемой в файле urls.py. 

Функции генерируют контент, который рендерится в html-шаблоне, размещенном в папке templates, и визуализируется в окне веб-браузера с применением таблиц стилей CSS.

Если «обернуть» такие функции в специальный декоратор (или создать вместо функций классы наследующие атрибуты встроенных в Django классов джинериков и миксин, что является более современным подходом) они будут способны обрабатывать REST-запросы от клиента.

Такие запросы (или ответы на них) могут содержать тело данных, записываемых (или извлекаемых) в базу данных, через процедуры сериализации (преобразования объекта (словаря данных) в строку байтов для передачи по линиям связи), десериализации (обратно сериализации) и валидации (проверку данных на соответствие ожидаемой структуре).

Для понимания элементарный пример такого взаимодействия, реализованного в приложении, представлен ниже.

Пользователь выбирает элемент управления, размещенный в окне браузера. К этому элементу подключен java-скрипт формирования, например, некоторого условного POST-запроса.

// Добавляем маркер
function saveMarkerToDatabase(coordinates, markerName) {
            fetch('https://swan-decent-shrew.ngrok-free.app/api/create_point/', {
                // Задаем метод REST-запроса
                method: 'POST',
                // Формируем хедер запроса
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': getCookie('csrftoken'), // Добавляем CSRF-токен в заголовок запроса
                },
                // Формируем тело запроса
                body: JSON.stringify({ name: markerName, location: 'SRID=4326;POINT(' + coordinates.lng + ' ' + coordinates.lat + ')' })
            });
}

В момент клика мыши по определенному url на сервер отправляется этот запрос, содержащий в своем теле контент: имя события и данные локации в формате WKT (код системы координат и проекции и координаты точки). Такой запрос, кроме тела, должен содержать служебную информацию в своем заголовке, защищающую приложение от внешних атак – CSRF-токен.

Связанная с этим url функция, ее еще называют эндпоинтом, успешно отрабатывает о чем свидетельствует статус ответа 200, если не возникают какие-либо исключения.

Возвращаемым результатом этой функции - представления будет некий контент. Это может быть файл формата GeoJSON, содержащий значения каким-то образом обработанные и записанные (извлеченные, обновленные, удаленные) в базу данных, а также, помещенные по определенным ключам в самом GeoJSON.

Например, по ключу «объекты» во вложенный список помещается геометрия объекта вместе с ее типом и, по ключу «свойства», - параметры атрибутов пространственных объектов, в данном примере это название инцидента.

{ "context_point_trek": { "type": "FeatureCollection", "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }, 
"features": [ 
{ "type": "Feature", "id": 1, "properties": { "name": "Точка: 1" }, "geometry": { "type": "Point", "coordinates": [ 158.839538, 53.572238 ] } }, 
{ "type": "Feature", "id": 2, "properties": { "name": "Точка: 2" }, "geometry": { "type": "Point", "coordinates": [ 158.83972, 53.572024 ] } }, (и так далее...)

Такой контент в виде переменных передается обратно в html-шаблон, где обрабатывается уже посредствам java-скриптов и стилизованно отображается в окне веб-браузера в виде слоев карты, таблиц, графиков, диаграмм и т.д., совместно с элементами пользовательского интерфейса (рисунок 3). Также такой контент может отдаваться в теле ответа на сформированный POST-запрос, для этого нужно лишь подкорректировать эндпоинт.

Рисунок – 3. Фрагмент пользовательского интерфейса приложения

Рисунок – 3. Фрагмент пользовательского интерфейса приложения

Для администрирования приложения, предназначается специальная панель Django, позволяющая создавать и удалять записи из базы данных пользователям, прошедшим процедуры идентификации и аутентификации (рисунок 4).

Рисунок – 4. Панель администрирования

Рисунок – 4. Панель администрирования

Для создания пользователя (на начальном этапе) используется команда

python manage.py createsuperuser

В дальнейшем, для регистрации новых пользователей приложения, этот функционал будет расширен.

Подытожить материал этой статьи хочется следующим. Логика веб-ГИС-приложения будет реализовывать инструменты получения спутниковых снимков с открытых ресурсов, например Sentinel Hub, и обработки полученных растров по специальным алгоритмам. Суть этой обработки заключается в комбинировании спектральных каналов спутниковых снимков и расчет спектральных индексов для решения задач на основе технологий машинного обучения: дешифрирования, классификации и кластеризации объектов и явлений местности. В дальнейшем также планируется внедрить в проект на основе этих наработок предобученные нейронные сети. Само собой это материалы для написания еще нескольких статей в дальнейшем. Будьте на связи, кому интересно подписывайтесь. 

В общем такой подход позволит реализовать ряд сервисов, размещенных в облаке, доступ к которым будет осуществляться по подписке. Клиенты будут использовать такие сервисы для конструирования собственных приложений, на подобии Notion.

Рисунок – 5. Менеджер задач служб реагирования

Рисунок – 5. Менеджер задач служб реагирования

Также планируется, возможность организации целой инфраструктуры (как вы наверно уже поняли, в минимально работоспособном варианте это уже реализовано), когда на основе сервисов можно будет создавать панели мониторинга, например мест скопления твердых бытовых отходов, незаконных застроек, зон пожаров и гарей, затоплений и многого другого. Такие дашборды смогут конструировать сами пользователи на основе предварительно созданного инструментария на стороне фронта (карт, таблиц, графиков, диаграмм и др.). Своего рода nocode-приложения для неподготовленных пользователей, либо с элементами кодирования, для более подготовленных, путем использования нашего API. Кроме того, мы сами сможем обеспечить всю цепочку создания, развертывания и поддержки приложения под более конкретные запросы пользователей.

Еще одним элементом этой инфраструктуры, станет возможность не только мониторить обстановку, но и отдавать распоряжения и контролировать их исполнение различным службам реагирования (рисунок 5), путем реализации дополнительного связанного с базой данных мобильного приложения (Android, IOS, и др. наше приложение платформонезависимо, в этом его прелесть!).

Видеопрезентация полного цикла работы приложения доступна по ссылке.

Автор: dilmah949

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js