Управление моделью Engee при помощи веб-приложения¶
В данной демонстрации мы проанализируем принципы реализации приложений управления моделями и сравним два варианта управления моделями – при помощи GenieFramework
и командного управления Engee.
Эти аспекты мы рассмотрим на примере модели генератора синусоиды и отслеживания выхода сигнала. Параметр «время симуляции» установим как «бесконечное».
Первый из вариантов управления такой моделью – это явное указание параметров из рабочей области Engee.
Теперь разберём логику самого приложения более подробно. Сама логика и интерфейс представлены в файле app.jl. Этот код создает интерактивное веб-приложение с использованием фреймворка GenieFramework и библиотек StippleUI и PlotlyBase для визуализации. Приложение позволяет управлять параметрами синусоидального сигнала через слайдеры и отображает график в реальном времени.
Блок @app
определяет модель данных:
@app begin
@in A = 1.0 # Амплитуда сигнала (начальное значение 1.0)
@in Fs = 1.0 # Частота сигнала (начальное значение 1.0)
@in P = 0.0 # Фаза сигнала (начальное значение 0.0)
@out plotdata = [scatter(x=vec(T), y=vec(sin.(2π .* T)))] # Начальные данные графика
@out plotlayout = PlotlyBase.Layout( # Настройки отображения графика
xaxis=attr(title="Время", showgrid=true),
yaxis=attr(title="Значение", showgrid=true)
)
При изменении параметров A, Fs или P мы обновляем график и передаём данные в модель, но, как вы можете заметить, делаем это уже не через рабочую область Engee, а через команду set_param
:
@onchange A, Fs, P begin
# Обновление данных графика с новыми параметрами
plotdata = [scatter(x=vec(T), y=vec(A .* sin.(2π * Fs .* T .+ P)))]
# Отправка параметров через Engee
engee.genie.send("A", A)
engee.genie.send("Fs", Fs)
engee.genie.send("P", P)
# Установка параметров в модуль SIN/Sin
engee.set_param!("SIN/Sin",
"Amplitude" => Float64(A),
"Frequency" => Float64(Fs),
"Phase" => Float64(P))
end
end
Функция ui()
определяет структуру веб-страницы:
function ui()
row([
column([ # Левая колонка с элементами управления
h6("Амплитуда = {{A}}", style="margin-bottom: -10px"),
slider(0.1:0.20:10, :A, color="red", style="margin-bottom: 20px"),
h6("Частота = {{Fs}}", style="margin-bottom: -10px"),
slider(0.1:0.20:10, :Fs, color="green", style="margin-bottom: 20px"),
h6("Фаза = {{P}}", style="margin-bottom: -10px"),
slider(0.0:0.20:2π, :P, color="blue", style="margin-bottom: 20px")
], style="width: 40%; padding: 20px;"),
column([ # Правая колонка с графиком
plot(:plotdata, layout=:plotlayout)
], style="width: 60%; padding: 20px; background-color: #f9f9f9; border-radius: 10px;")
])
end
Создание маршрута для главной страницы:
@page("/", ui, debounce=1)
Далее выполним запуск нашего приложения при помощи GenieFramework
.
app_url = string(engee.genie.start(string(@__DIR__,"/app.jl")))
app_url = replace((match(r"https?://[^\s\\]+", app_url)).match, r"\e$" => "")
println("URL: $app_url")
Приложение можно открыть как перейдя по ссылке, так и запустив его внутри ngscript
.
# display(
# MIME("text/html"),
# """<iframe
# src="$app_url"
# width="750" height="500"
# style="border: none;">
# </iframe>"""
# )
На рисунке ниже показано поведение модели под управлением веб-приложения.
Выключить приложение можно при помощи следующей команды:
# engee.genie.stop(string(@__DIR__,"/app.jl"))
Вывод¶
В этом примере было показано сразу два способа управления моделями при помощи GenieFramework, а также продемонстрированы возможности применения командного управления для реализации более крупных проектов в этом направлении.