Command/More/RunGraphizSample.ps1


Import-Module CmxModule -Force

$dotExePath = "D:\Programs\Graphviz\bin\dot.exe"
$inputFile = $env:Temp + "\GraphvizCode.gv"
$outputFile = "C:\Temp\GraphizOutput.png"

# https://graphviz.org/doc/info/attrs.html

$code = @'
digraph g
{
    layout = "dot"
    rankdir = "TB"
    fontname = "Arial"
    label = "OPC UA Safety Object Model"
    labelloc = "top"
    node [style = filled; fillcolor = yellow; color = dimgrey; fontcolor = black; fontname = "Arial"]
    edge [color = black; fontsize = 8; fontname = "Arial"; arrowhead = vee]
 
    subgraph cluster0
    {
        label = "";
        labelloc = "bottom";
        style = filled;
        color = white;
 
        n7 [label = "S7ControllerTargetData"; fillcolor = lightgrey]
        n1 [label = "FailsafeInfo"; fillcolor = yellow]
        n0 [label = "SafetyOverOpcUa \n Provider"; fillcolor = yellow]
        n2 [label = "DataBlockData"; fillcolor = lightgrey]
        n3 [label = "CodeBlockData"; fillcolor = lightgrey]
        n4 [label = "UserTypeData"; fillcolor = lightgrey]
        n5 [label = "FBlockInfo"; fillcolor = yellow]
        n6 [label = "FBlockInfo"; fillcolor = yellow]
 
        { rank = min; n7; }
        { rank = min; n1; }
        { rank = same; n0; }
        { rank = same; n2; n3; n4; }
        { rank = same; n5; n6; }
         
        edge[label = "SafetyOverOpcUa \n ProviderToFailsafeInfo \n 1"]
        n0 -> n1;
        edge[label = "FailsafeInfoTo \n SafetyOverOpcUa \n Provider \n *"]
        n1 -> n0;
        edge[label = "SafetyOverOpcUa \n ProviderToCoverInstanceDataBlock \n 1"]
        n0 -> n2;
        edge[label = "CoverInstanceDataBlockTo \n SafetyOverOpcUa \n Provider \n 1"]
        n2 -> n0;
        edge[label = "SafetyOverOpcUa \n ProviderToCoverFunctionBlock \n 1"]
        n0 -> n3;
        edge[label = "CoverFunctionBlockTo \n SafetyOverOpcUa \n Provider \n *"]
        n3 -> n0;
 
        edge[label = "SafetyOverOpcUa \n ProviderToUserTypeData \n 1"]
        n0 -> n4;
        edge[label = "UserTypeDataTo \n SafetyOverOpcUa \n Provider \n *"]
        n4 -> n0;
 
        edge[label = "NonSafetyData \n MappingExpandoLink \n 1"; style = dashed]
        n0 -> n4;
        edge[color = black; fontcolor = black]
 
        edge[label = "GeneralBlockSourceData \n ToBlockInfo \n 1"]
        n3 -> n5
 
        edge[label = "BlockInfo \n ToGeneralBlockSourceData \n 1"]
        n5 -> n3
 
        edge[label = "BlockInfo \n ToUserTypeData \n 1"]
        n5 -> n4
 
        edge[label = "BlockInfo \n ToNonSafetyUdt \n 1"; style = dashed]
        n5 -> n4
        edge[style = solid]
 
        edge[label = "UserTypeDataToBlockInfo \n *"]
        n4 -> n5
 
        edge[label = "GeneralBlockSourceData \n ToBlockInfo \n 1"]
        n2 -> n6
 
        edge[label = "BlockInfo \n ToGeneralBlockSourceData \n 1"]
        n6 -> n2
 
        edge[label = "BelongsTo \n 1"]
        n0 -> n7
 
        edge[label = "SWObjectsBelongingToMe \n *"]
        n7 -> n0
    }
 
    subgraph cluster1
    {
        rankdir = "TB"
        label = "Legend"
        labelloc = "bottom";
        style = filled;
        color = black;
        fillcolor = grey95;
 
        subgraph cluster2
        {
            label = "";
 
            l0 [label = "Failsafe Type"; fillcolor = yellow]
            l1 [label = "Standard Type"; fillcolor = lightgrey]
 
            edge [style = invis]
            l0 -> l2;
            edge [style = invis]
            l1 -> l3;
 
        }
         
        subgraph cluster3
        {
            label = "";
             
            l2 [label = "Type 1"; fillcolor = yellow]
            l3 [label = "Type 2"; fillcolor = lightgrey]
             
            edge[label = " Default Link "; style = solid]
            l2 -> l3;
            edge[label = " Expando Link "; style = dashed]
            l3 -> l2;
             
        }
 
        { rank = same; l0; l1; }
        { rank = same; l2; l3; }
    }
}
'@


$code = @'
digraph g
{
    layout = dot
    rankdir = TB
    fontname = "Arial"
    label = "Safety Provider Model Attributes"
    labelloc = "top"
 
    node [style = filled; fillcolor = yellow; color = dimgrey; fontcolor = black; fontname = "Arial"]
    edge [color = black; fontsize = 8; fontname = "Arial"]
 
    subgraph cluster0
    {
        label = "";
        labelloc = "bottom";
        style = filled;
        color = white;
 
        n1 [label = "SafetyOverOpcUa \n Provider"; fillcolor = yellow]
        n2 [label = "FBlockInfo"; fillcolor = yellow]
    }
 
    subgraph cluster1
    {
        label = "";
        labelloc = "bottom";
        style = filled;
        color = white;
 
        node [shape = record; fillcolor = lightgrey];
        set0
        [
            label = "{ICoreAttributes}"
        ];
 
        node [shape = record; fillcolor = yellow];
        set1
        [
            label = "{{ISafetyOverOpcUaProviderData} |
                { ProviderId : ulong } |
                { BaseId : Guid } |
                { Mapping : string } |
                { Namespace : string } |
                { InterfaceName : string } |
                { InterfaceId : string } |
                { ProviderDelay : uint } |
                { StructuredDataType : BlobT } |
                { GenericNodeId : BlobT } |
                { DataStatus : BlobT }
            }"
        ];
 
        node [shape = record; fillcolor = yellow];
        set2
        [
            label = "{{ISafetyOverOpcUaProviderDataExpando} |
                { NodeNamespaceIndices : OpcUaNodeNamespaceIndices } |
                { ActivateFsvMappingExpandoAttribute : string } |
                { NonSafetyDataMappingExpandoAttribute : string } |
                { NonSafetyDataTypeExpandoAttribute : OpcUaStructuredDataType } |
                { IsNonSafetyDataPlaceholderUsedExpandoAttribute : bool } |
                { NonSafetyDataMappingExpandoLink : IUdt }
            }"
        ];
 
        node [shape = record; fillcolor = yellow];
        set3
        [
            label = "{{IFBlockInfoExpando} |
                { BlockInfoToNonSafetyUdt : IUdt } |
                { . . . }
            }"
        ];
    }
 
    edge[arrowhead = diamond]
    n1 -> set0;
    n1 -> set1;
    n1 -> set2;
    n2 -> set3;
 
    { rank = min; n1; }
    { rank = same; set0; set1; }
}
'@

New-Item $inputFile -Force
Set-Content $inputFile $code
& $dotExePath -Tpng $inputFile -o $outputFile
Remove-Item $inputFile