Engee documentation
Notebook

Managing the Engee model using a web application

In this demo, we will analyze the principles of implementing model management applications and compare two model management options using GenieFramework and Engee command management.

We will consider these aspects using the example of a sine wave generator model and tracking the signal output. We will set the "simulation time" parameter as "infinite".

image.png

The first option for managing such a model is to explicitly specify parameters from the Engee workspace.

image.png

Now let's look at the logic of the application itself in more detail. The logic and interface itself are presented in the app.jl file. This code creates an interactive web application using the GenieFramework framework and the StippleUI and PlotlyBase libraries for visualization. The application allows you to control the parameters of the sinusoidal signal through sliders and displays a graph in real time.

Block @app defines the data model:

@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)
    )

When we change the parameters A, Fs, or P, we update the graph and transfer the data to the model, but as you can see, we no longer do this through the Engee workspace, but through the command 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

Function ui() defines the structure of a web page:

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

Creating a route for the home page:

@page("/", ui, debounce=1)

Next, we will run our application using GenieFramework.

In [ ]:
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")

The application can be opened either by clicking on the link or by launching it inside. ngscript.

In [ ]:
# display(
# MIME("text/html"),
# """<iframe
# src="$app_url"
# width="750" height="500"
# style="border: none;">
# </iframe>"""
# )
image_2.png

The figure below shows the behavior of the model under the control of a web application.

Запись 2025-06-05 174535.gif

You can turn off the application using the following command:

In [ ]:
# engee.genie.stop(string(@__DIR__,"/app.jl"))

Conclusion

This example showed two ways to manage models using GenieFramework at once, and also demonstrated the possibilities of using team management to implement larger projects in this area.

Blocks used in example