Visualizing SAP PI/PO with Squared Up

SAP Process Orchestration (or Integration) is a software within SAP which functions as data transformation gateway. It’s a central component of an SAP infrastructure and the standard way to communicate with external parties.

This post will show how to apply Squared Up’s “Single Pane of Glass” approach to SAP PI/PO.


SAP PI/PO offers a SOAP interface that can be used to gather information about the system.
In our case we are interested about the ‘health state’ of the individual communication channels.

As SOAP expects a XML payload and responds then in XML a ‘transformation’ is required as Squared Up only works with RESTful APIs.

To have a solution that can be applied to different cases a free & opensource Management Pack for SCOM has been created. It serves well for this particular task and can be extend if needed.



The configuration for SAP PO is rather simple. A normal user account needs to be created ( e.g.: in Active Directory ). In this example the user is called E11000.

In SAP PO – Identity Management then assign the roles of SAP_JAVA_NWADMIN_LOGVIEWER_ONLY and SAP_XI_APPL_SERV_USER

That’s all.

PowerShell – Test

Use the following code to test if all working as expected.

#global settings
$ErrorActionPreference = "stop"

#region Your_Configuration_Settings

$UserName      = 'E11000'
$PassWord      = 'ClearTextPassword'
$WebServiceUrl = 'https://servername:port/AdapterFramework/ChannelAdminServlet?party=*&service=*&channel=*&action=Status'

#endregion Your_Configuration_Settings

#region PREWORK Disabling the certificate validations

if ("TrustAllCertsPolicy" -as [type]) {
	$foo = 'already exist'
} else {
add-type -TypeDefinition @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
[Net.ServicePointManager]::CertificatePolicy = New-Object -TypeName TrustAllCertsPolicy

#endregion PREWORK

#region querying_SAP

$XMLNodeName   =  '//Channel'
$rtnMsg = ''

$header   = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($UserName+":"+ $PassWord))}

try {	
	$reqAnsw = Invoke-WebRequest -Uri $WebServiceUrl -UseBasicParsing -Headers $header -ContentType $ContentType
} catch {
	$rtnMsg = 'Failure during InvokeWebRequest' + $Error.ToString()

[xml]$content = $reqAnsw.Content
$elementList  = $content.DocumentElement.SelectNodes($XMLNodeName)

#endregion querying_SAP

#region converting_XML-To-PowerShellObjects

$allElements = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'

$elementList | ForEach-Object {
	$tmpString = $_ | Out-String  
	$tmpEntry  = $tmpString -Split("`r`n")  
	$tmpObj    = New-Object -TypeName PSObject

	$tmpEntry | ForEach-Object {  

		if ($_ -match '[a-zA-Z0-9]') {
			$tmpEntryItm = $_ -Split("\s{1}\:\s{1}")   
			$tmpItmLeft  = $tmpEntryItm[0] -Replace("\s","")
			$tmpItmRight = $tmpEntryItm[1] -Replace("\s","")
			Add-Member -InputObject $tmpObj -MemberType NoteProperty -Name $tmpItmLeft -Value $tmpItmRight        
	} #end $tmpEntry | ForEach-Object {}


} #end $elementList | ForEach-Object {}

#endregion converting_XML-To-PowerShellObjects

#region verifying_result

$allElements | Out-GridView

#endregion verifying_result 

The result of Out-GridView shall look similar to this one:


SCOM is here only used to run an Agent Task which queries the SOAP services and transforms the data to JSON.
The task consists of the Powershell script (mostly like above) which is then showing the results in Squared Up.

The agent task is part of a Management Pack named Windows.Computer.DataOnDemand.Addendum and can be downloaded via Community Catalog on or directly on GitHub .

After the Management Pack is important no further configuration in SCOM is required.

Squared Up

Dashboard Setup

Create an empty dashboard following the these steps:

1. Start with the SCOM Task tile
Select the SCOM Task Tile

2. Choose On-Demand Task (Grid)
Choose On-Demand Task (Grid)

3. Enter ANY Windows Server 2012 ( or higher ) which should query the PI/PO system.
Enter ANY Windows Server 2012 ( or higher )

4. Specify the task Get-RemoteSOAPServiceInfo (…)
Specify the task Get-RemoteSOAPServiceInfo (...)

5. Set at minimum the Overrides of PassWord UserName WebService URL and XMLNodeName
Set Overrides of PassWord UserName WebService URL and XMLNodeName

6. Choose which columns should be shown

7. Pick JSON as task return format
Pick json as task return format

8. Complete by enabling show column headers
Complete by enableing show column headers

The raw output should look similar to the one below:
Raw table format
The double hash tags ( ## ) are used later for improved visualization and can be disabled as Override Parameter.

Dashboard Styling

To make the dashboard now a bit more catchy, apply these steps.:

Edit the previously created SCOM task tile and select the Grid Columns section.

Start with editing column ‘Party‘ and paste in the following code:

{{#if (value.Party.substring(0,2) == "##") }} <span style="background-color:#E8E8E8;display: block;"> {{value.Party.replace("##","")}}  </span> {{else}}  {{value.Party}}  {{/if}}

Result after confirming with Done should be a grey background of every other row:

Result after confirming with Done

Add the same code with proper column names ( replace ‘Party’ with the corresponding one ) and the complete table will look good.

For completeness, here the code for ‘Direction‘ …

{{#if (value.Direction.substring(0,2) == "##") && (value.Direction.includes('OUTBOUND')) }} <span style="background-color:#E8E8E8;display: block;text-align: center;"> ▦ ->  </span>  {{elseif (value.Direction.substring(0,2) == "##") && (value.Direction.includes('INBOUND')) }} <span style="background-color:#E8E8E8;display: block;color:#0000ff;text-align: center;"> -> ▦  </span> {{elseif (value.Direction.substring(0,2) != "##") && (value.Direction.includes('INBOUND')) }} <span style="display: block;color:#0000ff;text-align: center;"> -> ▦ </span>   {{elseif (value.Direction.substring(0,2) != "##") && (value.Direction.includes('OUTBOUND')) }} <span style="display: block;text-align: center;"> ▦ -> </span>  {{/if}}

… and for ‘ChannelState‘:

{{#if (value.ChannelState.substring(0,2) == "##") && (value.ChannelState.includes('ERROR')) }} <span style="background-color:#E8E8E8;color:#ff0000;text-align: center;display: block;"> ✘  </span>  {{elseif (value.ChannelState.substring(0,2) == "##") && (value.ChannelState.includes('INACTIVE')) }} <span style="background-color:#E8E8E8;color:#000000;text-align: center;display: block;"> ⚪  </span> {{elseif (value.ChannelState.substring(0,2) == "##") && (value.ChannelState.includes('OK')) }} <span style="background-color:#E8E8E8;color:#00ff00;text-align: center;display: block;"> ✔  </span> {{elseif (value.ChannelState.substring(0,2) != "##") && (value.ChannelState.includes('ERROR')) }} <span style="color:#ff0000;text-align: center;display: block;"> ✘ </span>  {{elseif (value.ChannelState.substring(0,2) != "##") && (value.ChannelState.includes('INACTIVE')) }} <span style="color:#000000;text-align: center;display: block;"> ⚪  </span>  {{elseif (value.ChannelState.substring(0,2) != "##") && (value.ChannelState.includes('OK')) }} <span style="color:#00ff00;text-align: center;display: block;"> ✔  </span>  {{/if}} 

Last, but not least

If you have questions or comments, feel free to contact me.
You find me on twitter or on LinkedIn.

If the code isn’t running on your machine 😉
Or you like to add more features, please navigate the the corresponding GitHub site and raise an issue.