Этот пример показывает, как создать отчет, описывающий все объекты шины, используемые моделью. Этот отчет создает главу для каждого объекта шины. Каждая глава имеет раздел для иерархии шины, используемого - черным списком, таблицей свойств шины и таблицей свойств элементов шины.
Демонстрационный отчет объекта шины Simulink.
rptview asbhl20_bus_report.pdf
Откройте модель. Если Aerospace Blockset установлен, используйте модель asbhl20
в качестве примера, чтобы получить более всесторонний отчет объекта шины.
model = "sldemo_bus_arrays";
open_system(model);
Создайте и откройте объект отчета. Отключите свойство CompileModelBeforeReporting
потому что скомпилированная информация, собранная путем вызывания локальной функции busobjinfo
(см. ниже).
rpt = slreportgen.report.Report(model + "_bus_report", "pdf"); rpt.CompileModelBeforeReporting = false; open(rpt);
Добавьте titlepage и оглавление.
titlepage = mlreportgen.report.TitlePage("Title", model + ": Bus Object Report"); add(rpt, titlepage); toc = mlreportgen.report.TableOfContents(); add(rpt, toc);
Извлеките информацию об объекте шины из модели при помощи локальной функции busobjinfo
(см. ниже). Эта функция возвращает два значения, один для поиска объектов шины с имени шины и другого для поиска пользователя - блоками от имени шины.
[busMap, usersMap] = busobjinfo(model);
Получите все имена шины, используемые моделью.
busNames = keys(busMap);
Пройдите все объекты шины и создайте раздел для каждого объекта шины.
nBus = busMap.Count;
for i = 1:nBus
busName = busNames{i};
Создайте объект шины, разделяют и создают цель ссылки, таким образом, другие части отчета могут соединиться.
busID = createBusLinkID(busName); busSection = mlreportgen.report.Section( ... "Title", busName, ... "LinkTarget", busID);
Создайте подраздел иерархии объектов шины. Смотрите локальную функцию createBusHierarchyList
(см. ниже), для того, как пересечь через иерархию объектов шины, чтобы создать список иерархий шины.
hierarchySection = mlreportgen.report.Section("Hierarchy");
hierarchyList = createBusHierarchyList(busName, busMap, inf);
add(hierarchySection, hierarchyList);
add(busSection, hierarchySection);
Создайте используемый - разделом. Смотрите локальную функцию createUsedBySection
(см. ниже), для того, как видят, как создать подсвеченные системные снимки состояния и используемый списком.
usedBySection = createUsedBySection(busName, usersMap); add(busSection, usedBySection);
Составьте таблицу свойств объектов шины. Смотрите локальную функцию createBusPropertiesTable
(см. ниже), для того, как извлечь информацию об объекте шины, чтобы составить таблицу свойств шины.
busobjPropertiesSection = mlreportgen.report.Section("Properties");
propTable = createBusPropertiesTable(busName, busMap);
add(busobjPropertiesSection, propTable);
add(busSection, busobjPropertiesSection);
Составьте таблицу свойств элемента шины. Смотрите локальную функцию createBusElementsTable
(см. ниже), для того, как извлечь информацию об элементе шины и составить таблицу элементов шины.
elemsSection = mlreportgen.report.Section("Elements");
elemsTable = createBusElementsTable(busName, busMap);
add(elemsSection, elemsTable);
add(busSection, elemsSection);
Добавьте раздел объекта шины, чтобы сообщить, и очиститься подсвеченный используемый - блоками.
add(rpt, busSection); % Clear highlighted used-by blocks users = usersMap(busName); hilite_system(users, 'none'); end
Закройте отчет представления.
close(rpt); rptview(rpt);
Функция createBusHierarchyList
создает неупорядоченный список, описывающий иерархию объектов шины. Каждый элемент списка имеет внутреннюю ссылку к фрагменту элемента шины отчета. Входные параметры к этой функции являются именем шины, объектом busMap для решения объектов шины и номера, чтобы определить как далеко в иерархию, чтобы пересечь, чтобы создать список.
function list = createBusHierarchyList(busName, busMap, depth) % Create an unordered list. list = mlreportgen.dom.UnorderedList(); % Get bus object from name. busObj = busMap(busName); % Go through each bus element and create a linked list item. nBusElements = numel(busObj.Elements); for i = 1:nBusElements busElement = busObj.Elements(i); busElementName = busElement.Name; % Create a list item listItem = mlreportgen.dom.ListItem(); % Call createBusElementLinkID local function to get a link ID. busElementID = createBusElementLinkID(busName, busElementName); % If bus element is a known bus object, then create a sublist. Otherwise, % create a list item. busElementType = busElement.DataType; if isKey(busMap, busElementType) % Create a link to the bus element section label = compose("%s (%s)", busElementName, busElementType); internalLink = mlreportgen.dom.InternalLink(busElementID, label); append(listItem, internalLink); append(list, listItem); % Create sublist only if traversal depth is greater than 0. if (depth > 0) % Create sublist by recursively calling createBusHierarchyList % function. sublist = createBusHierarchyList(busElementType, busMap, depth - 1); append(list, sublist); end else % Create a link to the bus element section. internalLink = mlreportgen.dom.InternalLink(busElementID, busElementName); append(listItem, internalLink); append(list, listItem); end end end
Функция createUsedBySection
создает раздел, содержащий системные снимки состояния с блоками, подсветил, что используются - объектом шины. Снимки состояния сопровождаются используемым - списком блоков. Входные параметры к этой функции являются именем шины и объектом busMap для решения объектов шины.
function usedBySection = createUsedBySection(busName, usersMap) % Create used-by section usedBySection = mlreportgen.report.Section("Used-By"); % Get used-by list for a bus. allUsers = usersMap(busName); % Go through each block to determine which system they belong to and group them % with their parent system. Results are grouped in a containers.Map object to % allow for quick and easy lookup. sysUserMap = containers.Map(); nUsers = numel(allUsers); for i = 1:nUsers user = allUsers(i); % Get parent system. sys = get_param(user, "Parent"); if isKey(sysUserMap, sys) % Parent system already exists, append to list. sysUserMap(sys) = [sysUserMap(sys) user]; else % Create new system entry. sysUserMap(sys) = user; end end % Go through all systems. Note that all entries in a containers.Map are sorted. systems = keys(sysUserMap); nSys = sysUserMap.Count; for i = 1:nSys sys = systems{i}; % Get user list for a system. sysUsers = sysUserMap(sys); % Highlight users. sysUserHs = get_param(sysUsers, "Handle"); if iscell(sysUserHs) sysUserHs = cell2mat(sysUserHs); end hilite_system(sysUserHs); % Create system snapshot and add it to the used-by section. diag = slreportgen.report.Diagram(sys); add(usedBySection, diag); % Create unordered list of users. ul = mlreportgen.dom.UnorderedList(); if numel(sysUsers) == 1 append(ul, {sysUsers}); else append(ul, sysUsers); end add(usedBySection, ul); end end
Функция createBusPropertiesTable
составляет таблицу свойств шины, которая имеет два столбца. Один столбец для имен свойства, и второй столбец для значений свойств. Для свойства элементов createBusPropertiesTable
создает список иерархий, который указывает на фрагмент элемента шины отчета. Входные параметры к этой функции являются именем шины и объектом busMap для решения объектов шины.
function table = createBusPropertiesTable(busName, busMap) % Create an empty 2-column table, with solid borders. table = mlreportgen.dom.Table(2); table.Width = "100%"; table.Border = "solid"; table.ColSep = "solid"; table.RowSep = "solid"; % Set first column to 25% width and set second column to 75% width. cols = mlreportgen.dom.TableColSpecGroup(); cols.Span = 2; col1 = mlreportgen.dom.TableColSpec(); col1.Style = {mlreportgen.dom.Width("25%")}; col2 = mlreportgen.dom.TableColSpec(); col2.Style = {mlreportgen.dom.Width("75%")}; cols.ColSpecs = [col1, col2]; table.ColSpecGroups = cols; % Get bus object from name. busObj = busMap(busName); % Create a list of bus properties to report on. properties = [ ... "Elements" .... "DataScope" ... "HeaderFile" ... "Alignment" ... "Description" ... ]; % Go through bus properties list. for property = properties % Create table row row = mlreportgen.dom.TableRow(); % Create property name table entry. nameEntry = mlreportgen.dom.TableEntry(property); nameEntry.VAlign = "middle"; % Create property value table entry. value = busObj.(property); if isa(value, "Simulink.BusElement") % Property value is a bus element. Create a simple bus hierarchy list % by calling createBusHierarchyList with a depth of 0. valueDOMObj = createBusHierarchyList(busName, busMap, 0); else % Convert property value to a string. valueString = mlreportgen.utils.toString(value); valueDOMObj = mlreportgen.dom.Text(valueString); end valueEntry = mlreportgen.dom.TableEntry(); append(valueEntry, valueDOMObj); % Add name entry to row. append(row, nameEntry); % Add value entry to row. append(row, valueEntry); % Add row to table. append(table, row); end end
Функция createBusElementsTable
составляет таблицу элементов шины, которая имеет три столбца. Первый столбец имеет имена элементов шины, который охватывает несколько строк, чтобы группироваться свойства элемента шины. Второй столбец имеет имена свойства элемента шины, и третий столбец имеет значения свойств элемента шины. Для свойства datatype
элемента шины, если значение является объектом шины, то функция создает ссылку на раздел объекта шины. Входные параметры к этой функции являются именем шины и объектом busMap для решения объектов шины.
function table = createBusElementsTable(busName, busMap) % Create an empty 3 column table, with solid borders. table = mlreportgen.dom.Table(); table.Width = "100%"; table.Border = "solid"; table.ColSep = "solid"; table.RowSep = "solid"; % Set first column to 25% width, second column to 25% width, and third column to % 50% width. grps = mlreportgen.dom.TableColSpecGroup(); grps.Span = 3; specs1 = mlreportgen.dom.TableColSpec(); specs1.Style = {mlreportgen.dom.Width('25%')}; specs2 = mlreportgen.dom.TableColSpec(); specs2.Style = {mlreportgen.dom.Width('25%')}; specs3 = mlreportgen.dom.TableColSpec(); specs3.Style = {mlreportgen.dom.Width('50%')}; grps.ColSpecs = [specs1 specs2 specs3]; table.ColSpecGroups = grps; % Get bus object from name. busObj = busMap(busName); % List of bus element properties to report on. properties = [ ... "DataType", ... "Complexity", ... "Dimensions"... "DimensionsMode", ... "SampleTime", ... "Min", ... "Max", ... "Unit", ... "Description", ... ]; nProperties = numel(properties); % Go through all bus elements. busElements = busObj.Elements; nElements = numel(busElements); for i = 1:nElements % Create table row row = mlreportgen.dom.TableRow(); % Get bus element name. busElement = busElements(i); busElementName = busElement.Name; % Create bus element link target, so other internal links can point to it. busElementID = createBusElementLinkID(busName, busElementName); busElementLinkTarget = mlreportgen.dom.LinkTarget(busElementID); busElementPara = mlreportgen.dom.Paragraph(busElementName); append(busElementPara, busElementLinkTarget); % Create table entry for first column with element name and target. busElementEntry = mlreportgen.dom.TableEntry(); append(busElementEntry, busElementPara); % Set bus element row to span the number of bus element properties. This % groups together bus element properties to the bus element row. busElementEntry.RowSpan = nProperties; busElementEntry.InnerMargin = "2pt"; busElementEntry.VAlign = "middle"; % Add bus element name entry to row. append(row, busElementEntry); % Go through bus element properties for property = properties % First row is not empty because it was created above to hold the bus % element name. if isempty(row) row = mlreportgen.dom.TableRow(); end % Create table entry for bus element property. propNameEntry = mlreportgen.dom.TableEntry(property); propNameEntry.InnerMargin = "2pt"; % Get bus element value. value = busElement.(property); valueString = mlreportgen.utils.toString(value); if (strcmp(property, "DataType") && isKey(busMap, valueString)) % Bus element value is a bus object data type. Create a link to bus % object section. propValueEntry = mlreportgen.dom.TableEntry(); busID = createBusLinkID(valueString); busLink = mlreportgen.dom.InternalLink(busID, valueString); append(propValueEntry, busLink); else propValueEntry = mlreportgen.dom.TableEntry(valueString); end propValueEntry.InnerMargin = "2pt"; % Append bus elment table property name and value entries. append(row, propNameEntry); append(row, propValueEntry); % Append bus element property table row. append(table, row); % Clear row to allow for bus bus element property rows. row = []; end % bus element properties end % bus element end
Функция busobjinfo
находит все объекты шины используемыми моделью и возвращает busMap и userMap. busMap, containers.Map возражает, что карты соединяют шиной имя к объекту шины. userMap, containers.Map возражает, что сопоставляет имя шины к отсортированному списку модели, подсистем, и блокируется, tthat используют объект шины.
function [busMap, userMap] = busobjinfo(model) % Create containers.Map to store bus object information. A containers.Map data % type allows for quick lookup of bus object information based on bus names. busMap = containers.Map(); userMap = containers.Map(); % Find all model variables, including model references. results = Simulink.findVars(model, "SearchReferencedModels", "on"); % Get model workspace to resolve variable names. modelWorkspace = get_param(model, "ModelWorkspace"); % Go through all search results. nResults = numel(results); for i = 1:nResults result = results(i); name = result.Name; source = result.Source; % Resolve variable value based on source type. switch lower(result.SourceType) case "base workspace" % Variable is defined in base workspace. Determine variable value by % calling EVALIN. value = evalin("base", name); case "model workspace" % Variable is defined in model workspace. Determine variable value % from model workspace object. value = getVariable(modelWorkspace, "name"); case "mask workspace" % Variable is defined in mask workspace. Get mask object and find % variable to determine value. maskObj = Simulink.Mask.get(source); vars = getWorkspaceVariables(maskObj); idx = strcmp({vars.Name}, name); value = vars(idx).Value; case "data dictionary" % Variable is defined in data dictionary. Open data dictionary to % and get variable name entry to determine variable value. dict = Simulink.data.dictionary.open(source); sect = getSection(dict, "Design Data"); entry = getEntry(sect, result.Name); value = getValue(entry); end % If variable value is a Simulink.Bus, then store results in maps. if isa(value, "Simulink.Bus") busMap(name) = value; userMap(name) = sort(string(result.Users)); end end end
Соединение от одного местоположения документа до другого местоположения документа в документе требует соответствующей строки и для источника и для места назначения. Эта строка называется идентификатором ссылки. Следующие две локальных функции создают идентификаторы ссылки для объекта шины и соединяют шиной элементы.
function id = createBusElementLinkID(busName, busElement) % Bus element id consists of the bus name and bus element name. It is hashed to % force the id to be no longer than 40 characters. An id longer than 40 % characters may not work in Microsoft Word documents. id = mlreportgen.utils.hash(compose("bus-element-%s-%s", busName, busElement)); end function id = createBusLinkID(busName) % Bus id is the bus name. It is hashed to force the id to be no longer than 40 % characters. An id longer than 40 characters may not work in Microsoft Word % documents. id = mlreportgen.utils.hash(compose("bus-%s", busName)); end