WEB – КОНСТРУКТОР МАСШТАБИРУЕМЫХ РОБОТЕХНИЧЕСКИХ СИСТЕМ МОДЕЛИРОВАНИЯ СЛОЖНЫХ ПОВЕРХНОСТЕЙ ДЛЯ ДИНАМИЧЕСКИХ ИСПЫТАНИЙ
- Авторы: Графкин А.В., Мыльников Е.Н., Понамаренко Д.И.
- Выпуск: № 2(21) (2022)
- Страницы: 78-86
- Раздел: Информатика и вычислительная техника
- Дата публикации: 09.08.2023
- URL: https://vmuis.ru/smus/article/view/10602
- ID: 10602
Цитировать
Полный текст
Аннотация
В данной статье описывается процесс проектирования распределенной системы SaaS, реализующей функции WEB – конструктора с использованием фреймворка Django на языке программирования Python. В качестве системы управления базой данных (СУБД) используется PostgreSQL. Разбираются основные функции взаимодействия с базой данных: создание (create), чтение (read), редактирование (update), удаление (delete) - CRUD. Для взаимодействия сервисов системы используется REST API. Интерфейс пользователя реализован в виде клиента с помощью шаблонов html с применением стилей bootstrapcdn. Для упрощения отладки используются методы логирования. Координация работы разработчиков обеспечивается с помощью системы контроля версий Git и сервера контроля версий GitHub.
Ключевые слова
Полный текст
Введение. В настоящее время все чаще используются WEB-приложения, так как в отличии от стандартных приложений, данные программы способны полноценно работать без установки на компьютер. WEB - конструктор проектируется с учетом возможности построения динамической системы, позволяющей моделировать сложные поверхности, которые формируются с помощью множества Stewart – платформ (рис. 1). Параметр каждой платформы (базового модуля системы) можно задать через конфигуратор соответствующего устройства. Количество устройств может меняться динамически, конфигурация динамической системы задается в конструкторе.
Рис. 1. Stewart-платформа
Проектируемая роевая система роботов состоит из Stewart – платформ и может использоваться как испытательный стенд. WEB-конструктор с распределенной системой SааS позволяет в режиме онлайн изменять систему (менять количество, расположение и характеристики), для моделирования сложных поверхностей под конкретную задачу с помощью конфигуратора.
SaaS (software as a service - программное обеспечение как услуга) - одна из форм облачных вычислений, модель обслуживания, при которой подписчикам предоставляется готовое прикладное программное обеспечение, полностью обслуживаемое провайдером. Поставщик в этой модели самостоятельно управляет приложением, предоставляя заказчикам доступ к функциям с клиентских устройств через веб-браузер [1].
Конструктор отвечает за хранение, загрузку и выгрузку законов движения – закон, по которому будет изменяться положение в пространстве базового модуля. Каждый базовый модуль изменяет свое положение согласно заданного закона движения. В совокупности базовые модули Stewart – платформ образуют систему Stewart – платформ, а законы движения каждого отдельного модуля вместе – закон движения системы.
Проектирование базы данных проекта. Анализируя предметную область, можно выделить следующие сущности – «Система Stewart платформ», «Stewart платформа» (базовый модуль), «Закон движения платформы». Система и базовый модуль имеют связь «один ко многим», так как в одной системе может быть много базовых модулей, но конкретный базовый модуль может быть только в одной системе. Базовый модуль и закон движения платформы имеют связь один ко многим, так как у закона может быть много базовых модулей, но базовый модуль может работать только по одному закону движения. Разработаем ER – модель базы данных (рис.2).
Рис. 2. ER - модель базы данных
Параметры закона движения хранятся в базе данных в виде JSON поля:
{"time start": 0, "step": 1, "repeat": 5, "coordinates": {"x": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}, "y": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}, "z": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}, "a": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}, "b": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}, "g": {"0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0}}}, где
"time start": время начала движения базового модуля,
"step": шаг, частота дискретизации от времени начала движения,
"repeat": количество повторений шага,
"coordinates": {“x”, “y”, “z”, “a”, “b”, “g”,}: координаты относительно осей в пространстве, где каждому моменту времени соответствует координата.
Программная реализация базы данных проекта. На первом этапе необходимо установить PostgreSQL локально на компьютер. Затем создать базу данных в PostgreSQL и учетную запись Admin [2].
Чтобы подключить созданную базу данных к Django необходимо установить модуль psycopg2. В файле settings.py/DATABASE необходимо прописать следующие настройки:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'BD_system_stewart_platform',
'USER': 'Admin',
'PASSWORD': 'adminadmin',
'HOST': 'localhost',
'PORT': '',}}
Чтобы создать таблицы в базе данных необходимо прописать следующий код в файле models.py:
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class system_stewart_platform(models.Model):
title_system = models.CharField('Наименование системы', max_length=50)
discription_system = models.CharField('Описание системы', max_length=500)
LAW_TYPE=(
('Волна', 'Волна'),
('Колебания', 'Колебания'),)
law_type_system = models.CharField(verbose_name='Закон движения системы', max_length=50, choices=LAW_TYPE, null=False, blank=True, default='Волна', help_text='Выбрать из списка')
x_max_matrix = models.IntegerField('Размер матрицы по оси x')
y_max_matrix = models.IntegerField('Размер матрицы по оси y')
author = models.ForeignKey(User,related_name='system_stewart_platform_user_created', verbose_name='Пользователь', on_delete=models.CASCADE, null=True,blank=True, default=None)
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Добавлено")
time_update = models.DateTimeField(auto_now=True, verbose_name="Изменено")
def _str_(self):
return self.title_system
def get_absolute_url(self):
return reverse('systemDetailView', args=[str(self.id)])
class Meta:
verbose_name = 'Система Stewart Platform'
verbose_name_plural = 'Системы Stewart Platform'
class law_for_platform(models.Model):
law_type_plat = models.CharField('Наименование типа закона', max_length=50)
amplitude = models.IntegerField('Амплитуда закона от 0 до 100')
coordinates_t = models.JSONField('Координаты и параметры для платформы')
author = models.ForeignKey(User, related_name='law_for_platform_wave_user_created',
verbose_name='Пользователь', on_delete=models.CASCADE, null=True,
blank=True, default=None)
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Добавлено")
time_update = models.DateTimeField(auto_now=True, verbose_name="Изменено")
def _str_(self):
return self.law_type_plat
def get_absolute_url(self):
return reverse('LawDetailView', args=[str(self.id)])
class Meta:
verbose_name = 'Закон движения для базового модуля'
verbose_name_plural = 'Законы движения для базового модуля'
class stewart_platform(models.Model):
system_stewart_platform = models.ForeignKey(system_stewart_platform, verbose_name='Система', on_delete=models.CASCADE)
law_type = models.ForeignKey(law_for_platform, verbose_name='Закон движения платформы', on_delete=models.CASCADE)
title_platform = models.CharField('Наименование базового модуля', max_length=50)
discription_platform = models.CharField('Описание базового модуля', max_length=500)
ip_adress = models.GenericIPAddressField('IP адрес', protocol='both', unpack_ipv4=False)
port_platform = models.PositiveSmallIntegerField('Порт подключения', default=0)
position_x_in_matrix = models.IntegerField('Позиция базового модуля по оси х')
position_y_in_matrix = models.IntegerField('Позиция базового модуля по оси у')
author = models.ForeignKey(User, related_name='stewart_platform_user_created',
verbose_name=u'Пользователь', on_delete=models.CASCADE, null=True,blank=True, default=None)
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Добавлено")
time_update = models.DateTimeField(auto_now=True, verbose_name="Изменено")
def _str_(self):
return self.title_platform
def get_absolute_url(self):
return reverse('platformDetailView', args=[str(self.id)])
class Meta:
verbose_name = 'Базовый модуль'
verbose_name_plural = 'Базовые модули'
С помощью команды в терминале «python manage.py createsuperuser» создаем учетную запись администратора, назначаем логин и пароль. Проводим миграции с помощью команд в терминале: «python manage.py makemigrations» и «python manage.py migrate» и регистрируем ее в панели администратора в файле admin.py:
from django.contrib import admin
from .models import system_stewart_platform, stewart_platform, law_for_platform
admin.site.register(system_stewart_platform)
admin.site.register(stewart_platform)
admin.site.register(law_for_platform)
Наполним базу данных информацией, заполнив таблицы система Stewart platform, базовый модуль Stewart platform и закон движения, например, через панель администратора или используя команды в терминале. Проверим корректность наполнения базы данных в PostgreSQL, сделав SELECT запрос (рис.3) [3].
Рис. 3. Проверка базы данных в PostgreSQL
Реализация CRUD в проекте. CRUD — акроним, обозначающий четыре базовые функции, используемые при работе с базами данных: создание (create), чтение (read), модификация (update), удаление (delete). В данном проекте реализована возможность добавления, редактирования, удаления и просмотра систем Stewart platform, базового модуля Stewart platform и закона движения Stewart platform. Реализованы формы для добавления и редактирования, а также возможности удаления экземпляров. Пользователь видит на сайте все объекты, а также отдельные страницы каждого экземпляра. Для реализации CRUD в проекте принято решение воспользоваться встроенными в Django модулями ListView, DetailView, CreateView, UpdateView, DeleteView. На первом этапе необходимо импортировать модули в файл views.py. Используем классовый подход создания views, а не функционально – ориентированный. Модуль reverse_lazy нужен для переадресации на нужную нам страницу после добавления экземпляра в базу данных.
Для того, чтобы просматривать, добавлять, изменять и удалять данные из базы данных могли только авторизованные пользователи создадим класс LoginRequiredMixin и воспользуемся методом декоратором @method_decorator(login_required). Таким образом код во view.py будет выглядеть следующим образом:
from .models import *
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class LoginRequiredMixin(object):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
class systemListView(LoginRequiredMixin, ListView):
model = system_stewart_platform
template_name = "systemStewartPlatform/system/systemListView.html"
class systemDetailView(LoginRequiredMixin, DetailView):
model = system_stewart_platform
template_name = "systemStewartPlatform/system/systemDetailView.html"
class systemCreateView(LoginRequiredMixin, CreateView):
model = system_stewart_platform
template_name = 'systemStewartPlatform/system/systemCreateView.html'
fields = ['title_system', 'discription_system', 'law_type_system', 'x_max_matrix', 'y_max_matrix', 'author']
class systemEditView(LoginRequiredMixin, UpdateView):
model = system_stewart_platform
template_name = 'systemStewartPlatform/system/systemEditView.html'
fields = ['title_system', 'discription_system', 'law_type_system', 'x_max_matrix', 'y_max_matrix', 'author']
class systemDeleteView(LoginRequiredMixin, DeleteView):
model = system_stewart_platform
template_name = 'systemStewartPlatform/system/systemDeleteView.html'
success_url = reverse_lazy('home')
class platformListView(LoginRequiredMixin, ListView):
model = stewart_platform
template_name = "systemStewartPlatform/platform/platformListView.html"
class platformDetailView(LoginRequiredMixin, DetailView):
model = stewart_platform
template_name = "systemStewartPlatform/platform/platformDetailView.html"
class platformCreateView(LoginRequiredMixin, CreateView):
model = stewart_platform
template_name = 'systemStewartPlatform/platform/platformCreateView.html'
fields = ['system_stewart_platform', 'law_type', 'title_platform', 'discription_platform', 'ip_adress', 'port_platform', 'position_x_in_matrix',
'position_y_in_matrix', 'author']
class platformEditView(LoginRequiredMixin, UpdateView):
model = stewart_platform
template_name = 'systemStewartPlatform/platform/platformEditView.html'
fields = ['system_stewart_platform', 'law_type', 'title_platform', 'discription_platform', 'ip_adress', 'port_platform', 'position_x_in_matrix',
'position_y_in_matrix', 'author']
class platformDeleteView(LoginRequiredMixin, DeleteView):
model = stewart_platform
template_name = 'systemStewartPlatform/platform/platformDeleteView.html'
success_url = reverse_lazy('home')
class LawListView(LoginRequiredMixin, ListView):
model = law_for_platform
template_name = "systemStewartPlatform/law/LawListView.html"
class LawDetailView(LoginRequiredMixin, DetailView):
model = law_for_platform
template_name = "systemStewartPlatform/law/LawDetailView.html"
class LawCreateView(LoginRequiredMixin, CreateView):
model = law_for_platform
template_name = 'systemStewartPlatform/law/LawCreateView.html'
fields = ['law_type_plat', 'amplitude', 'coordinates_t', 'author']
class LawEditView(LoginRequiredMixin, UpdateView):
model = law_for_platform
template_name = 'systemStewartPlatform/law/LawEditView.html'
fields = ['law_type_plat', 'amplitude', 'coordinates_t', 'author']
class LawDeleteView(LoginRequiredMixin, DeleteView):
model = law_for_platform
template_name = 'systemStewartPlatform/law/LawDeleteView.html'
success_url = reverse_lazy('home')
Затем для каждого созданного нами нового представления необходимо прописать маршруты в urls.py:
from django.urls import path
from .views import *
urlpatterns = [
path('systemListView', systemListView.as_view(), name='systemListView'),
path('systemDetailView/<int:pk>/', systemDetailView.as_view(), name='systemDetailView'),
path('systemNewView', systemCreateView.as_view(), name='systemCreateView'),
path('systemDetailView/<int:pk>/edit/', systemEditView.as_view(), name='systemEditView'),
path('systemDeleteView/<int:pk>/delete/', systemDeleteView.as_view(), name='systemDeleteView'),
path('platformListView', platformListView.as_view(), name='platformListView'),
path('platformDetailView/<int:pk>/', platformDetailView.as_view(), name='platformDetailView'),
path('platformNewView', platformCreateView.as_view(), name='platformCreateView'),
path('platformDetailView/<int:pk>/edit/', platformEditView.as_view(), name='platformEditView'),
path('platformDeleteView/<int:pk>/delete/', platformDeleteView.as_view(), name='platformDeleteView'),
path('LawListView', LawListView.as_view(), name='LawListView'),
path('LawDetailView/<int:pk>/', LawDetailView.as_view(), name='LawDetailView'),
path('LawNewView', LawCreateView.as_view(), name='LawCreateView'),
path('LawDetailView/<int:pk>/edit/', LawEditView.as_view(), name='LawEditView'),
path('LawDeleteView/<int:pk>/delete/', LawDeleteView.as_view(), name='LawDeleteView'),]
Также для каждого созданного маршрута и представления необходимо создать шаблон html, который будет отображаться на сайте при переходе по адресу страницы.
Для проверки работы CRUD запустим тестовый сервер (рис.4).
Рис. 4. Интерфейс WEB-конструктора с реализованными функциями CRUD
Реализация REST API в проекте. В системах, реализующих доступ к базе данных через API в стиле REST, функции CRUD реализуются зачастую через HTTP-методы PUT, POST, GET, PATCH, DELETE.
API (Application Programming Interface) – это программный интерфейс. Он обеспечивает взаимодействие двух программ между собой и позволяет встраивать контент с любого сайта. Основной задачей API является создание связи между двумя приложениями. API позволяет отправлять запросы на передачу или получение информации. Взаимодействие осуществляется через JSON, а данные получаем в приложениях с помощью API - запросов. API - запрос включает в себя 4 компонента: endpoint (точка приема запроса), header (заголовок), method (метод) и data (данные). После вызова всех компонентов мы можем построить API - запрос [4].
Для реализации REST API в проекте необходимо установить модуль djangorestframework. Затем создать новое отдельное приложение в нашем проекте используя команду «python manage.py startapp LawAPI».
В файл setting.py в INSTALLED_APPS необходимо добавить созданное нами новое приложение, а также «rest_framework». Создадим новый словарь в файле настроек для задания необходимых нам параметров djangorestframework:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 2,
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated']}
Создадим файл serialazers.py, в котором создадим сериалайзер для наших моделей:
from rest_framework import serializers
from systemStewartPlatform.models import *
class systemSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default = serializers.CurrentUserDefault())
class Meta:
model = system_stewart_platform
fields = '__all__'
class platformSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default = serializers.CurrentUserDefault())
class Meta:
model = stewart_platform
fields = '__all__'
class lawSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default = serializers.CurrentUserDefault())
class Meta:
model = law_for_platform
fields = '__all__'
Затем создадим представления в файле views.py, где укажем queryset и serializer_class:
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet
from lawAPI.serializers import *
from systemStewartPlatform.models import *
class systemViewSet(ModelViewSet):
queryset = system_stewart_platform.objects.all()
serializer_class = systemSerializer
class platformViewSet(ModelViewSet):
queryset = stewart_platform.objects.all()
serializer_class = platformSerializer
class lawViewSet(ModelViewSet):
queryset = law_for_platform.objects.all()
serializer_class = lawSerializer
В файле urls.py пропишем маршруты используя модуль djangorestframework routers:
from rest_framework import routers
from lawAPI.views import *
router = routers.SimpleRouter()
router.register(r'system', systemViewSet)
router.register(r'platform', platformViewSet)
router.register(r'law', lawViewSet)
Реализованный функционал REST API продемонстрирован на рисунке 5.
Рис. 5. REST API
Заключение. В работе разработан проект WEB-конструктора для построения динамической системы, позволяющей моделировать сложные поверхности, которые формируются с помощью множества Stewart – платформ. Настроен Фреймворк Django, спроектирована база данных. Для реализации возможности добавления, редактирования, удаления и просмотра базы данных с сайта реализован CRUD с использованием форм и REST API. Экспериментальная проверка, запущенного локально сервера сайта в отладочном режиме демонстрирует правильную работу разработанного функционала.
Об авторах
Алексей Викторович Графкин
Email: lvg_alex@mail.ru
Доцент кафедры безопасности информационных систем Самарского государственного университета
РоссияЕвгений Николаевич Мыльников
Автор, ответственный за переписку.
Email: mylnikov.yevgeniy@gmail.com
Россия
Денис Иванович Понамаренко
Email: maestrodark@icloud.com
Россия
Список литературы
- SaaS. URL: https://ru.wikipedia.org/wiki/Программное_обеспечение_как_услуга (дата обращения: 10.08.2022).
- What is PostgreSQL. URL: http://www.sai.msu.su/~megera/postgres/talks/what_is_postgresql.html (дата обращения: 10.08.2022).
- Васильев, А. Ю. Работа с PostgreSQL настройка и масштабирование: учебное пособие/ А. Ю. Васильев. – California: Creative Commons, 2017. — 203 с.
- Django Rest Framework URL: https://www.django-rest-framework.org/ (дата обращения: 11.08.2022).