Моделирование насос-форсунки EUI
Author
# =============================================================================
# profile_sync.jl — Синхронизация с Engee
# =============================================================================
using DataInterpolations
using Printf
using Engee
function sync_profile(data;
use_cubic::Bool = true,
output_file::String = OUTPUT_FILE,
input_export::String = "ui_profile_export.data")
println("=== НАЧАЛО СИНХРОНИЗАЦИИ СХЕМЫ В ENGEE ===")
println("Выходной файл профиля: ", output_file)
target_disp_mm = zeros(Float64, 361)
web_data_ok = false
sliders_changed = false
file_uid = ""
ui_method = use_cubic ? "cubic" : "linear"
if isfile(input_export)
println("ℹ Обнаружен файл $input_export. Чтение...")
try
for line in readlines(input_export)
line = strip(line)
# Ищем UID в шапке файла
m_uid = match(r"#\s*UID:\s*(\w+)", line)
m_uid !== nothing && (file_uid = String(m_uid.captures[1]))
occursin("SLIDERS_CHANGED: true", line) && (sliders_changed = true)
m_method = match(r"#\s*INTERP_METHOD:\s*(\w+)", line)
m_method !== nothing && (ui_method = String(m_method.captures[1]))
(isempty(line) || startswith(line, "#") ||
startswith(line, "Table") || occursin("<", line)) && continue
parts = split(line)
length(parts) < 2 && continue
try
angle = round(Int, parse(Float64, parts[1]))
val_mm = parse(Float64, parts[2])
(0 <= angle <= 360) && (target_disp_mm[angle + 1] = val_mm)
catch
continue
end
end
any(target_disp_mm .!= 0.0) && (web_data_ok = true)
catch e
println("⚠ Ошибка чтения файла: ", e)
end
else
println("ℹ Файл $input_export не найден.")
end
# Проверяем, что файл принадлежит ТЕКУЩЕЙ сессии (UID совпадает) и ползунки двигались
session_matches = (file_uid == uid) && (uid != "")
if web_data_ok && sliders_changed && session_matches
println("✔ Данные успешно прочитаны. Применяем кастомный профиль из UI.")
else
if web_data_ok && !session_matches
println("ℹ Файл $input_export от другой сессии или старый (UID не совпадает). Игнорируем.")
elseif web_data_ok && !sliders_changed
println("ℹ Ползунки не менялись. Игнорируем $input_export и применяем исходный профиль.")
else
println("ℹ Применяем исходный профиль для параметризации.")
end
# Используем исходный профиль + Akima (как в UI)
base_interp = if ui_method == "linear"
DataInterpolations.LinearInterpolation(data.raw_disp .* 1e3, data.raw_angles)
else
DataInterpolations.AkimaInterpolation(data.raw_disp .* 1e3, data.raw_angles)
end
for (idx, angle) in enumerate(0.0:1.0:360.0)
if ui_method == "linear" || angle <= 70.0
target_disp_mm[idx] = base_interp(angle)
else
y70 = base_interp(70.0)
progress = (angle - 70.0) / (360.0 - 70.0)
v = y70 * (1.0 - progress) + 1.2 * y70 * progress * (1.0 - progress)
target_disp_mm[idx] = v < 0 ? 0.0 : v
end
end
println(" → Использован метод: ", ui_method)
end
try
open(output_file, "w") do io
println(io, "# Table format: 1D")
for angle in 0:360
val_mm = target_disp_mm[angle + 1]
println(io, "\t", angle, "\t", lowercase(@sprintf("%.6e", val_mm)))
end
end
println("✔ 1. Итоговый файл профиля записан: ", output_file)
catch e
error("Ошибка записи файла: ", e)
end
try
global Angle = collect(0.0:1.0:360.0)
global Disp = target_disp_mm .* 1e-3
final_spline = DataInterpolations.CubicSpline(Disp, Angle)
global Dh_Ddeg = Float64[DataInterpolations.derivative(final_spline, a) for a in Angle]
println("✔ 2. Векторы Angle, Disp, Dh_Ddeg отправлены в Engee.")
println(" - Максимальный ход: ", maximum(Disp) * 1e3, " мм")
catch e
error("Ошибка параметризации: ", e)
end
return nothing
end