classdef configJs % Класс для работы с JSON конфигурацией периферии в масках Simulink % Обеспечивает чтение, запись и обновление конфигов из/в JSON файлы methods(Static) function config = update(blockPath, config) % Обновляет конфигурацию значениями из маски Simulink % blockPath - путь к блоку с маской % config - структура конфигурации для обновления if isempty(config) return; end % Получаем маску и все её параметры mask = Simulink.Mask.get(blockPath); maskParams = mask.Parameters; paramNames = arrayfun(@(p) p.Name, maskParams, 'UniformOutput', false); % Обрабатываем все секции периферии в конфиге periphs = fieldnames(config); for i = 1:numel(periphs) periph = periphs{i}; % Проверяем есть ли секция Defines в этой периферии if ~isfield(config.(periph), 'Defines') continue; end % Получаем все определения (defines) для этой периферии defines = config.(periph).Defines; defNames = fieldnames(defines); % Обходим все определения и обновляем их значения из маски for j = 1:numel(defNames) defPrompt = defNames{j}; paramName = matlab.lang.makeValidName(defPrompt); % Создаем валидное имя параметра % Проверяем существует ли параметр с таким именем в маске if ismember(paramName, paramNames) param = mask.getParameter(paramName); valStr = param.Value; % Значение как строка из маски % Проверяем существует ли элемент defPrompt в структуре defines if isfield(defines, defPrompt) % Преобразуем строку из маски в соответствующий тип данных if strcmpi(defines.(defPrompt).Type, 'checkbox') % Для чекбоксов преобразуем 'on'/'off' в true/false config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on'); elseif strcmpi(defines.(defPrompt).Type, 'edit') % Для текстовых полей пробуем преобразовать в число valNum = str2double(valStr); if isnan(valNum) % Если не число - оставляем строкой config.(periph).Defines.(defPrompt).Default = valStr; else % Если число - сохраняем как число config.(periph).Defines.(defPrompt).Default = valNum; end end end end end end end function config = read(blockPath) % Читает JSON конфигурацию из файла указанного в маске % blockPath - путь к блоку с маской % Возвращает структуру конфигурации или пустой массив mask = Simulink.Mask.get(blockPath); % Получаем путь к конфигурационному файлу из параметра маски pathparam = mask.getParameter('periphPath'); config_path = pathparam.Value; if ~isempty(config_path) % Читаем и декодируем JSON файл jsonText = fileread(config_path); config = jsondecode(jsonText); else config = []; end end function write(config) % Записывает конфигурацию обратно в JSON файл % config - структура конфигурации для записи if isempty(config) return end % Получаем handle текущего блока и его маску blockHandle = gcbh; mask = Simulink.Mask.get(blockHandle); % Получаем путь к конфигурационному файлу из маски pathparam = mask.getParameter('periphPath'); config_path = pathparam.Value; % Кодируем структуру в JSON с красивым форматированием jsonText = jsonencode(config, 'PrettyPrint', true); % Записываем JSON в файл fid = fopen(config_path, 'w', 'n'); if fid == -1 error('Не удалось открыть файл periph_config.json для записи.'); end fwrite(fid, jsonText, 'char'); fclose(fid); end function value = get_field(configStruct, targetConfig) % Рекурсивно ищет поле в структуре конфигурации % configStruct - структура для поиска % targetConfig - имя целевого поля % Возвращает значение поля или пустой массив если не найдено value = []; fields = fieldnames(configStruct); for i = 1:numel(fields) key = fields{i}; if strcmp(key, targetConfig) % Нашли прямое совпадение value = configStruct.(key); return; elseif isstruct(configStruct.(key)) % Рекурсивно ищем во вложенной структуре value = configJs.get_field(configStruct.(key), targetConfig); if ~isempty(value) return; % Нашли во вложенной структуре end end end % Если не нашли - возвращаем пустой массив if isempty(value) % Можно раскомментировать для отладки: % error('Поле "%s" не найдено в структуре.', targetConfig); end end function short = get_final_name_from_prefix(prefix) % Извлекает короткое имя из префикса (последняя часть после '_') % prefix - строка с префиксом вида 'PREFIX_NAME' % Возвращает последнюю часть после последнего '_' parts = strsplit(prefix, '_'); short = parts{end}; % Берём последний элемент end function value = convert_code_value(codeField) % Преобразует значение поля Options в строку для отображения % Обрабатывает разные типы данных: char, string, cell array if ischar(codeField) value = codeField; elseif isstring(codeField) value = char(codeField); elseif iscell(codeField) % Объединяем ячейки в одну строку с переносами value = strjoin(codeField, newline); else % Для неподдерживаемых типов возвращаем пустую строку value = ''; end end end methods(Static, Access=private) % Приватные методы могут быть добавлены здесь при необходимости end end