{
  "productInfo" : {
    "company" : "HighByte",
    "product" : "IntelligenceHub",
    "version" : "4.5.0",
    "build" : "2026.8.14.399",
    "stage" : "Release"
  },
  "project" : {
    "version" : 14,
    "connections" : [ {
      "name" : "pi_sp",
      "uri" : "osisoft.afsdk://{{System.Variables.reference_host}}:45299",
      "groupAs" : "/solution_patterns",
      "description" : "This is a Connection to AVEVA PI System.  \nThis Connection supports solution patterns.  \nHighByte note: this Connection uses a dedicated agent installed on a demo system EC2.",
      "tags" : [ "historian1_historization", "historian2_replication", "historian3_specialization" ],
      "writes" : {
        "flattenModeledValues" : false
      },
      "writeThrottle" : {
        "enabled" : false,
        "maxBatchSizePerTarget" : 1000,
        "batchDelay" : {
          "duration" : 20,
          "units" : "Milliseconds"
        }
      },
      "subscriptions" : { },
      "storeForward" : {
        "enabled" : false,
        "maxEntries" : 100,
        "waitOnFailureInterval" : {
          "duration" : 1,
          "units" : "Seconds"
        }
      },
      "settings" : {
        "connectTimeoutSeconds" : 5,
        "requestTimeoutMS" : 120000,
        "compression" : "GZIP",
        "auth" : {
          "type" : "credentials",
          "username" : "osisoft",
          "password" : {
            "type" : "Reference",
            "value" : "pi_password"
          }
        },
        "password" : {
          "type" : "Reference",
          "value" : "pi_token_reference"
        }
      }
    }, {
      "name" : "postgresql_sp",
      "uri" : "jdbc.postgresql://{{System.Variables.connections_host}}:5432",
      "groupAs" : "/solution_patterns",
      "description" : "This is a Connection to the local PostgreSQL database.  This Connection supports Solution Patterns.",
      "tags" : [ "historian1_historization", "historian2_replication", "historian3_specialization", "telemetry1_value_opc", "telemetry1_value_sparkplug", "telemetry2_asset_opc", "telemetry2_asset_sparkplug", "telemetry3_downtime", "telemetry4_maintenance" ],
      "writes" : {
        "flattenModeledValues" : false
      },
      "writeThrottle" : {
        "enabled" : false,
        "maxBatchSizePerTarget" : 1000,
        "batchDelay" : {
          "duration" : 20,
          "units" : "Milliseconds"
        }
      },
      "subscriptions" : { },
      "storeForward" : {
        "enabled" : true,
        "maxEntries" : 2000,
        "waitOnFailureInterval" : {
          "duration" : 10,
          "units" : "Seconds"
        }
      },
      "settings" : {
        "strategy" : {
          "type" : "default"
        },
        "database" : "solution_patterns",
        "username" : "postgres",
        "password" : {
          "type" : "Reference",
          "value" : "postgresql_password"
        },
        "connectString" : "reWriteBatchedInserts=true&stringtype=unspecified"
      }
    }, {
      "name" : "sap_sp",
      "uri" : "rest.client://sap",
      "groupAs" : "/solution_patterns",
      "description" : "This Connection interacts with SAP APIs available at the SAP Business Accelerator Hub [https://api.sap.com/]. Specifically, the Maintenance Order API https://api.sap.com/api/API_MAINTENANCEORDER/overview.\nThis Connection supports Solution Patterns.",
      "tags" : [ "historian3_specialization", "telemetry4_maintenance" ],
      "writes" : {
        "flattenModeledValues" : false
      },
      "writeThrottle" : {
        "enabled" : false,
        "maxBatchSizePerTarget" : 1000,
        "batchDelay" : {
          "duration" : 20,
          "units" : "Milliseconds"
        }
      },
      "subscriptions" : { },
      "storeForward" : {
        "enabled" : false,
        "maxEntries" : 100,
        "waitOnFailureInterval" : {
          "duration" : 1,
          "units" : "Seconds"
        }
      },
      "settings" : {
        "authentication" : {
          "type" : "None",
          "options" : { }
        },
        "baseURL" : "https://sandbox.api.sap.com:443"
      }
    } ],
    "inputs" : [ {
      "name" : "pi_input_current_values_maintenance",
      "connection" : "pi_sp",
      "type" : "osisoft.afsdk",
      "qualifier" : {
        "type" : "point",
        "options" : {
          "get" : "average",
          "includeMetaData" : false,
          "includeChildren" : true,
          "useReference" : true,
          "points" : [ ],
          "query" : "",
          "index" : false,
          "indexWindow" : "",
          "calcBasis" : "timeWeighted",
          "format" : "JSON",
          "reference" : "{{this.reference}}",
          "boundaryType" : "inside",
          "startTime" : "{{this.startTime}}",
          "endTime" : "{{this.endTime}}",
          "interval" : "1h"
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "inline",
        "model" : {
          "name" : "params",
          "tags" : [ ],
          "attributes" : [ {
            "attributeType" : "Internal",
            "name" : "reference",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : [ "Grains.05071eb9-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ebc-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ebf-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ec2-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ec5-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ec8-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ecb-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ed2-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071ed5-fcdd-11ee-ba85-060be97f82e1.Value Imperial", "Grains.05071edc-fcdd-11ee-ba85-060be97f82e1.Value Imperial" ],
            "internalType" : {
              "variant" : "String"
            }
          }, {
            "attributeType" : "Internal",
            "name" : "startTime",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : "2025-11-01T00:00:00.000Z",
            "internalType" : {
              "variant" : "String"
            }
          }, {
            "attributeType" : "Internal",
            "name" : "endTime",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : "2025-11-01T01:00:00.000Z",
            "internalType" : {
              "variant" : "String"
            }
          } ],
          "modelVersion" : ""
        }
      }
    }, {
      "name" : "pi_input_point_subscription",
      "connection" : "pi_sp",
      "type" : "osisoft.afsdk",
      "qualifier" : {
        "type" : "pointdatapipe",
        "options" : {
          "get" : "currentValue",
          "includeMetaData" : false,
          "includeChildren" : true,
          "useReference" : true,
          "format" : "JSON",
          "reference" : "{{Connection.pi_sp.pi_input_points_list}}",
          "subscriptionId" : "pi_input_point_subscription_08-15",
          "maxPerRead" : 10000,
          "query" : "",
          "index" : false,
          "indexWindow" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "pi_input_points_list",
      "connection" : "pi_sp",
      "type" : "osisoft.afsdk",
      "qualifier" : {
        "type" : "pointbrowse",
        "options" : {
          "get" : "currentValue",
          "includeMetaData" : false,
          "includeChildren" : true,
          "query" : "*Grains*",
          "index" : false,
          "indexWindow" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : true,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "pi_input_verify_pi_point_update",
      "connection" : "pi_sp",
      "type" : "osisoft.afsdk",
      "qualifier" : {
        "type" : "point",
        "options" : {
          "get" : "currentValue",
          "includeMetaData" : false,
          "includeChildren" : true,
          "useReference" : false,
          "points" : [ "Grains.05071f35-fcdd-11ee-ba85-060be97f82e1.Value Imperial" ],
          "query" : "",
          "index" : false,
          "indexWindow" : "",
          "calcBasis" : "timeWeighted",
          "format" : "JSON"
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_downtime_event",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT * FROM \"public\".\"downtime_event\" ORDER BY \"startTime\" DESC LIMIT 100;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_north_field_opc_tags_attribute",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n  replace(regexp_replace(topic, '^PermianBasin/NorthField/', ''), '/', '.') AS \"opcTagPath\",\n  substring(path from '[^/]+$')                                             AS \"newAttribute\",\n  path\nFROM path_mapping\nWHERE topic LIKE '%NorthField%'\n  AND (substring(topic from 'Channel(\\d+)/'))::int <= 10;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_north_field_opc_tags_pi_point",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n  replace(regexp_replace(topic, '^PermianBasin/NorthField/', ''), '/', '.') AS \"opcTagPath\",\n  substring(path from '[^/]+$')                                             AS \"newAttribute\",\n  path,\n  \"piPoint\"\nFROM path_mapping\nWHERE topic LIKE '%NorthField%'\n  AND (substring(topic from 'Channel(\\d+)/'))::int <= 10;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_north_field_opc_tags_pump",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "-- One row per asset. Three OPC UA tag paths pivoted into columns.\n-- opcTagPath = topic, dot-delimited, 'PermianBasin/NorthField/' prefix removed.\n-- path = asset path (full path minus the metric leaf).\nSELECT\n  regexp_replace(path, '/[^/]*$', '')                                          AS \"path\",\n  MAX(CASE WHEN topic ~ '/OutboundFlowPressure[0-9]+$'\n      THEN replace(regexp_replace(topic, '^PermianBasin/NorthField/', ''), '/', '.') END) AS \"dischargePressure\",\n  MAX(CASE WHEN topic ~ '/TargetNozzleFlowRate[0-9]+$'\n      THEN replace(regexp_replace(topic, '^PermianBasin/NorthField/', ''), '/', '.') END) AS \"flowRate\",\n  MAX(CASE WHEN topic ~ '/ThroatFlowPressure[0-9]+$'\n      THEN replace(regexp_replace(topic, '^PermianBasin/NorthField/', ''), '/', '.') END) AS \"intakePressure\"\nFROM path_mapping\nWHERE topic LIKE '%NorthField%'\n  AND (topic ~ '/OutboundFlowPressure[0-9]+$'\n    OR topic ~ '/TargetNozzleFlowRate[0-9]+$'\n    OR topic ~ '/ThroatFlowPressure[0-9]+$')\nGROUP BY regexp_replace(path, '/[^/]*$', '')\nORDER BY \"path\";",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_process_data",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT * FROM \"public\".\"process_data\" ORDER BY \"inserted_at\"  DESC LIMIT 100;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_pumps_centrifugal",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT * FROM \"public\".\"process_data_pumps_centrifugal\"",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_south_field_maintenance_data",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n    regexp_replace(\"path\", '/[^/]+$', '') AS \"path\",\n    MAX(\"workCenter\") AS \"workCenter\",\n    MAX(CASE WHEN topic LIKE '%MotorCurrent%' THEN \"piPoint\" END) AS \"MotorCurrent\",\n    MAX(CASE WHEN topic LIKE '%MotorTemp%'    THEN \"piPoint\" END) AS \"MotorTemp\"\nFROM path_mapping\nWHERE split_part(topic, '/', 2) = 'SouthField'\n  AND substring(split_part(topic, '/', 3) FROM 4)::int <= 5\n  AND (topic LIKE '%MotorCurrent%' OR topic LIKE '%MotorTemp%')\nGROUP BY regexp_replace(\"path\", '/[^/]+$', '')\nORDER BY \"path\";",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "inline",
        "model" : {
          "name" : "params",
          "tags" : [ ],
          "attributes" : [ {
            "attributeType" : "Internal",
            "name" : "assetPath",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : "site01/area01/line01/asset01",
            "internalType" : {
              "variant" : "String"
            }
          } ],
          "modelVersion" : ""
        }
      }
    }, {
      "name" : "postgresql_input_south_field_maintenance_status",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n    split_part(topic, '/', 1)                       AS \"group\",\n    split_part(topic, '/', 2)                       AS \"edgeNode\",\n    split_part(topic, '/', 3)                       AS \"device\",\n    regexp_replace(topic, '^([^/]+/){3}', '')       AS \"metric\",\n    path                                            AS \"path\",\n    \"workCenter\",\n    replace(regexp_replace(topic, '^([^/]+/){3}', ''), '/', '.') AS \"metricDecimal\"\nFROM path_mapping\nWHERE split_part(topic, '/', 2) = 'SouthField'\n  AND substring(split_part(topic, '/', 3) FROM 4)::int <= 5\n  AND \"path\" LIKE '%{{this.assetPath}}%'\n  AND topic LIKE '%RunStatus%'\nORDER BY topic;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "inline",
        "model" : {
          "name" : "params",
          "tags" : [ ],
          "attributes" : [ {
            "attributeType" : "Internal",
            "name" : "assetPath",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : "site01/area01/line01/asset01",
            "internalType" : {
              "variant" : "String"
            }
          } ],
          "modelVersion" : ""
        }
      }
    }, {
      "name" : "postgresql_input_south_field_sparkplug_run_status",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n    split_part(topic, '/', 1)                       AS \"group\",\n    split_part(topic, '/', 2)                       AS \"edgeNode\",\n    split_part(topic, '/', 3)                       AS \"device\",\n    regexp_replace(topic, '^([^/]+/){3}', '')       AS \"metric\",\n    regexp_replace(path, '/[^/]*$', '')             AS \"path\",\n    regexp_replace(path, '.*/', '')                 AS \"newAttribute\",\n    replace(regexp_replace(topic, '^([^/]+/){3}', ''), '/', '.') AS \"metricDecimal\"\nFROM path_mapping\nWHERE split_part(topic, '/', 2) = 'SouthField'\n  AND substring(split_part(topic, '/', 3) FROM 4)::int <= 5\n  AND topic LIKE '%RunStatus%'\nORDER BY topic;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_south_field_sparkplug_topics_attribute",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n    split_part(topic, '/', 1)                       AS \"group\",\n    split_part(topic, '/', 2)                       AS \"edgeNode\",\n    split_part(topic, '/', 3)                       AS \"device\",\n    regexp_replace(topic, '^([^/]+/){3}', '')       AS \"metric\",\n    path                                            AS \"path\",\n    regexp_replace(path, '.*/', '')                 AS \"newAttribute\",\n    replace(regexp_replace(topic, '^([^/]+/){3}', ''), '/', '.') AS \"metricDecimal\"\nFROM path_mapping\nWHERE split_part(topic, '/', 2) = 'SouthField'\n  AND substring(split_part(topic, '/', 3) FROM 4)::int <= 5\nORDER BY topic;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "postgresql_input_south_field_sparkplug_topics_well",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "type" : "query",
        "query" : "SELECT\n    split_part(topic, '/', 1)                       AS \"group\",\n    split_part(topic, '/', 2)                       AS \"edgeNode\",\n    split_part(topic, '/', 3)                       AS \"device\",\n    split_part(topic, '/', 4)                       AS \"metric\",\n    regexp_replace(path, '/[^/]*$', '')             AS \"path\"\nFROM path_mapping\nWHERE split_part(topic, '/', 2) = 'SouthField'\n  AND substring(split_part(topic, '/', 3) FROM 4)::int <= 5\nORDER BY topic;",
        "index" : {
          "enabled" : false,
          "indexName" : "",
          "indexValue" : ""
        }
      },
      "cacheLifetime" : {
        "enabled" : false,
        "interval" : {
          "duration" : 1,
          "units" : "Days"
        }
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "sap_input_list_maintenance_work_centers",
      "connection" : "sap_sp",
      "type" : "rest.client",
      "qualifier" : {
        "acceptType" : "*/*",
        "method" : "GET",
        "contentType" : "application/json",
        "includeMetadata" : false,
        "endpointURL" : "/s4hanacloud/sap/opu/odata/sap/API_MAINTENANCEORDER/MaintenanceOrder?$select=MainWorkCenter,MainWorkCenterPlant&$top=100&$format=json",
        "isFile" : false,
        "header" : [ {
          "name" : "APIKey",
          "value" : "{{System.Variables.sap_key}}"
        }, {
          "name" : "content-type",
          "value" : "application/json"
        } ]
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    }, {
      "name" : "sap_input_next_maintenance_order_for_work_center",
      "connection" : "sap_sp",
      "type" : "rest.client",
      "qualifier" : {
        "acceptType" : "*/*",
        "method" : "GET",
        "contentType" : "application/json",
        "includeMetadata" : false,
        "endpointURL" : "/s4hanacloud/sap/opu/odata/sap/API_MAINTENANCEORDER/MaintenanceOrder?$filter=MainWorkCenter eq '{{this.workCenter}}' and MaintOrdProcessPhaseCode ne '09'&$top=1&$format=json",
        "isFile" : false,
        "header" : [ {
          "name" : "APIKey",
          "value" : "{{System.Variables.sap_key}}"
        }, {
          "name" : "content-type",
          "value" : "application/json"
        } ]
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "type" : "Off"
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "inline",
        "model" : {
          "name" : "params",
          "tags" : [ ],
          "attributes" : [ {
            "attributeType" : "Internal",
            "name" : "workCenter",
            "nullable" : false,
            "required" : false,
            "array" : false,
            "defaultValue" : "RES-0300",
            "internalType" : {
              "variant" : "String"
            }
          } ],
          "modelVersion" : ""
        }
      }
    }, {
      "name" : "sap_input_next_maintenance_orders_for_work_centers",
      "connection" : "sap_sp",
      "type" : "rest.client",
      "qualifier" : {
        "acceptType" : "*/*",
        "method" : "GET",
        "contentType" : "application/json",
        "includeMetadata" : false,
        "endpointURL" : "/s4hanacloud/sap/opu/odata/sap/API_MAINTENANCEORDER/MaintenanceOrder?$filter=MainWorkCenter eq '{{this.workCenter}}' and MaintOrdProcessPhaseCode ne '09'&$orderby=MaintOrdSchedldBscStrtDateTime asc&$top=1&$format=json",
        "isFile" : false,
        "header" : [ {
          "name" : "APIKey",
          "value" : "{{System.Variables.sap_key}}"
        }, {
          "name" : "content-type",
          "value" : "application/json"
        } ]
      },
      "cacheLifetime" : {
        "enabled" : false
      },
      "template" : {
        "name" : "{{this.workCenter}}",
        "type" : "Static",
        "params" : [ {
          "name" : "workCenter",
          "pattern" : "\"RES-0300\",\"RES-0200\",\"RES-0100\""
        } ]
      },
      "referenceMap" : [ ],
      "parameters" : {
        "type" : "EmptyParameters"
      }
    } ],
    "outputs" : [ {
      "name" : "pi_output_point",
      "connection" : "pi_sp",
      "type" : "osisoft.afsdk",
      "qualifier" : {
        "type" : "point",
        "breakupArrays" : false,
        "options" : {
          "updateOption" : "Insert",
          "create" : false
        },
        "filterList" : [ "_name", "_model", "_timestamp" ]
      }
    }, {
      "name" : "postgresql_output_downtime_event_end",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "writeType" : "update",
        "createOption" : "off",
        "breakupArrays" : false,
        "tableCacheInterval" : {
          "duration" : 1,
          "units" : "Hours"
        },
        "table" : "downtime_event",
        "whereColumn" : "\"path\" = '{{this.path}}'\n  AND \"endTime\" IS NULL\n  AND \"startTime\" IS NOT NULL\n  AND '{{this.endTime}}'::timestamp >= \"startTime\" + INTERVAL '1 minute';",
        "logAsJSON" : false,
        "filterList" : [ "_name", "_model", "_timestamp" ]
      }
    }, {
      "name" : "postgresql_output_downtime_event_start",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "writeType" : "insert",
        "createOption" : "off",
        "breakupArrays" : false,
        "tableCacheInterval" : {
          "duration" : 1,
          "units" : "Hours"
        },
        "table" : "downtime_event",
        "whereColumn" : "",
        "logAsJSON" : false,
        "filterList" : [ "_name", "_model", "_timestamp" ]
      }
    }, {
      "name" : "postgresql_output_process_data",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "writeType" : "insert",
        "createOption" : "off",
        "breakupArrays" : false,
        "tableCacheInterval" : {
          "duration" : 1,
          "units" : "Hours"
        },
        "table" : "process_data",
        "whereColumn" : "",
        "logAsJSON" : false,
        "filterList" : [ "_model", "_name", "_timestamp" ]
      }
    }, {
      "name" : "postgresql_output_process_data_pumps_centrifugal",
      "connection" : "postgresql_sp",
      "type" : "jdbc.postgresql",
      "qualifier" : {
        "writeType" : "upsert",
        "createOption" : "create",
        "breakupArrays" : false,
        "tableCacheInterval" : {
          "duration" : 1,
          "units" : "Hours"
        },
        "table" : "process_data_pumps_centrifugal",
        "whereColumn" : "\"path\" = '{{this.path}}'",
        "filterList" : [ "_name", "_model", "_timestamp" ],
        "logAsJSON" : false
      }
    } ],
    "modeling" : {
      "models" : [ {
        "name" : "maintenance_data",
        "description" : "This model structures a payload of maintenance status information.",
        "groupAs" : "/historian",
        "tags" : [ "historian3_specialization" ],
        "attributes" : [ {
          "attributeType" : "Internal",
          "name" : "assetPath",
          "nullable" : false,
          "required" : true,
          "array" : false,
          "internalType" : {
            "variant" : "String"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "workCenterSAP",
          "nullable" : false,
          "required" : true,
          "array" : false,
          "internalType" : {
            "variant" : "String"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "maintenaceOrderSAP",
          "nullable" : false,
          "required" : true,
          "array" : false,
          "internalType" : {
            "variant" : "String"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "maintenanceDescription",
          "nullable" : true,
          "required" : false,
          "array" : false,
          "internalType" : {
            "variant" : "String"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "maintenanceStartDate",
          "nullable" : true,
          "required" : false,
          "array" : false,
          "internalType" : {
            "variant" : "DateTime"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "motorCurrent",
          "nullable" : false,
          "required" : true,
          "array" : false,
          "internalType" : {
            "variant" : "Real64"
          }
        }, {
          "attributeType" : "Internal",
          "name" : "motorTemp",
          "nullable" : false,
          "required" : true,
          "array" : false,
          "internalType" : {
            "variant" : "Real64"
          }
        } ],
        "modelVersion" : ""
      } ],
      "instances" : [ ]
    },
    "conditions" : [ ],
    "functions" : [ ],
    "tags" : [ {
      "name" : "historian3_specialization"
    } ],
    "pipelines" : [ {
      "name" : "maintenance_data_to_rest_server",
      "description" : "A unique asset path is provided to this Pipeline, and the Pipeline obtains the pump's current process values from PI and the next maintenance order from SAP.\n\n",
      "groupAs" : "/historian",
      "tags" : [ "historian3_specialization" ],
      "inputStages" : [ "parameter_to_metadata" ],
      "stages" : [ {
        "name" : "parameter_to_metadata",
        "display" : {
          "position" : {
            "x" : 240,
            "y" : 0
          }
        },
        "description" : "This Stage moves the incoming asset path parameter to metadata.",
        "config" : {
          "type" : ".AttributeFilterConfig",
          "filterOption" : "exclude",
          "filterList" : [ {
            "filterType" : "exactPathFilter",
            "filterText" : "assetPath"
          }, {
            "filterType" : "exactPathFilter",
            "filterText" : "endTime"
          }, {
            "filterType" : "exactPathFilter",
            "filterText" : "startTime"
          } ],
          "retainAsMetadata" : true,
          "metadataKey" : "parameter"
        },
        "outputs" : [ "read_mapping" ]
      }, {
        "name" : "create_pi_point_list",
        "display" : {
          "position" : {
            "x" : 1140,
            "y" : 0
          }
        },
        "description" : "This Stage formats the PI Points for the Read Stage.",
        "config" : {
          "type" : ".JavaScriptTransformConfig",
          "transformExpression" : "var input = event.value;\r\n\r\nvar points = Object.keys(input)\r\n    .filter(function (k) {\r\n        var v = input[k];\r\n        return typeof v === \"string\" && /^Grains\\..+\\.Value Imperial$/.test(v);\r\n    })\r\n    .map(function (k) { return input[k]; });\r\n\r\ninput.points = points;\r\n\r\nstage.setValue(input);"
        },
        "outputs" : [ "merge_read" ]
      }, {
        "name" : "apply_model",
        "display" : {
          "position" : {
            "x" : 2040,
            "y" : 0
          }
        },
        "description" : "This Stage applies the desired Model.",
        "config" : {
          "type" : ".ModelConfig",
          "model" : "maintenance_data",
          "objectName" : "",
          "initExpression" : "",
          "attributes" : [ {
            "name" : "assetPath",
            "expression" : {
              "type" : "PipelineStageReference",
              "stageReference" : "event.metadata.parameter.assetPath"
            }
          }, {
            "name" : "workCenterSAP",
            "expression" : {
              "type" : "PipelineStageReference",
              "stageReference" : "event.value.sap.MainWorkCenter"
            }
          }, {
            "name" : "maintenaceOrderSAP",
            "expression" : {
              "type" : "PipelineStageReference",
              "stageReference" : "event.value.sap.MaintenanceOrder"
            }
          }, {
            "name" : "maintenanceDescription",
            "expression" : {
              "type" : "PipelineStageReference",
              "stageReference" : "event.value.sap.MaintenanceOrderDesc"
            }
          }, {
            "name" : "maintenanceStartDate",
            "expression" : {
              "type" : "JavaScript",
              "expression" : "// Convert SAP OData /Date(ms±offset)/ strings to ISO 8601 (UTC)\r\nfunction sapDateToIso(v) {\r\n  if (typeof v !== \"string\") return v;\r\n  var m = v.match(/^\\/Date\\((-?\\d+)([+-]\\d{4})?\\)\\/$/);\r\n  if (!m) return v;                       // not a SAP date, leave as-is\r\n  return new Date(Number(m[1])).toISOString();\r\n}\r\n\r\n// Walk the payload and convert only SAP-date strings; everything else untouched\r\nfunction convert(node) {\r\n  if (Array.isArray(node)) return node.map(convert);\r\n  if (node && typeof node === \"object\") {\r\n    var out = {};\r\n    for (var k in node) {\r\n      if (Object.prototype.hasOwnProperty.call(node, k)) out[k] = convert(node[k]);\r\n    }\r\n    return out;\r\n  }\r\n  return sapDateToIso(node);\r\n}\r\nlet sapTime = event.value.sap.MaintOrdBasicStartDateTime;\r\nreturn convert(sapTime);"
            }
          }, {
            "name" : "motorCurrent",
            "expression" : {
              "type" : "JavaScript",
              "expression" : "let point = event.value.mappings.MotorCurrent\r\nreturn event.value.pi[point].value;"
            }
          }, {
            "name" : "motorTemp",
            "expression" : {
              "type" : "JavaScript",
              "expression" : "let point = event.value.mappings.MotorTemp\r\nreturn event.value.pi[point].value;"
            }
          } ],
          "expandArray" : false
        },
        "outputs" : [ "return" ]
      }, {
        "name" : "read_mapping",
        "display" : {
          "position" : {
            "x" : 690,
            "y" : 0
          }
        },
        "description" : "This Stage obtains the PI Points and SAP mappings.",
        "config" : {
          "type" : ".ReadConfig",
          "failureOutputs" : [ ],
          "reference" : {
            "type" : "LookupMap",
            "name" : "south_field_mappings",
            "path" : "[\"{{event.metadata.parameter.assetPath}}\"]"
          },
          "handleGoodNoData" : false,
          "goodNoDataOutputs" : [ ]
        },
        "outputs" : [ "create_pi_point_list" ]
      }, {
        "name" : "merge_read",
        "display" : {
          "position" : {
            "x" : 1590,
            "y" : 0
          }
        },
        "description" : "This Stage obtains data from PI and SAP given the unique asset.",
        "config" : {
          "type" : ".MergeReadConfig",
          "failureOutputs" : [ ],
          "keyReferences" : [ {
            "location" : "child",
            "key" : "sap",
            "reference" : {
              "type" : "LookupMap",
              "name" : "sap_maintenance_orders",
              "path" : "[\"{{event.value.workCenter}}\"]"
            }
          }, {
            "location" : "child",
            "key" : "pi",
            "reference" : {
              "type" : "Input",
              "name" : "pi_input_current_values_maintenance",
              "path" : "[0].values",
              "params" : {
                "reference" : "{{event.value.points}}",
                "startTime" : "{{event.metadata.parameter.startTime}}",
                "endTime" : "{{event.metadata.parameter.endTime}}"
              },
              "connectionName" : "pi_sp"
            }
          } ],
          "inputValueLocation" : "child",
          "inputValueKey" : "mappings"
        },
        "outputs" : [ "apply_model" ]
      }, {
        "name" : "return",
        "display" : {
          "position" : {
            "x" : 2490,
            "y" : 0
          }
        },
        "description" : "",
        "config" : {
          "type" : ".ReturnConfig"
        },
        "outputs" : [ ]
      } ],
      "trackActivity" : false,
      "queueSize" : 10000,
      "triggers" : [ {
        "name" : "api_trigger",
        "display" : {
          "position" : {
            "x" : -450,
            "y" : 0
          }
        },
        "description" : "The Pipeline executes when called from an external source.",
        "config" : {
          "type" : ".TriggerApi",
          "enabled" : true,
          "parameters" : {
            "type" : "inline",
            "model" : {
              "name" : "params",
              "tags" : [ ],
              "attributes" : [ {
                "attributeType" : "Internal",
                "name" : "assetPath",
                "nullable" : false,
                "required" : false,
                "array" : false,
                "defaultValue" : "site01/area01/line01/asset01",
                "internalType" : {
                  "variant" : "String"
                }
              }, {
                "attributeType" : "Internal",
                "name" : "startTime",
                "nullable" : false,
                "required" : false,
                "array" : false,
                "defaultValue" : "2025-11-01T00:00:00.000Z",
                "internalType" : {
                  "variant" : "Any"
                }
              }, {
                "attributeType" : "Internal",
                "name" : "endTime",
                "nullable" : false,
                "required" : false,
                "array" : false,
                "defaultValue" : "2025-11-01T01:00:00.000Z",
                "internalType" : {
                  "variant" : "Any"
                }
              } ],
              "modelVersion" : ""
            }
          }
        }
      } ],
      "errorHandler" : {
        "type" : "default"
      }
    }, {
      "name" : "sap_maintenance_orders_for_lookup",
      "description" : "This Pipeline obtains a list of maintenance orders from SAP and formats them for a look up table.",
      "groupAs" : "/general",
      "tags" : [ "telemetry4_maintenance", "historian3_specialization" ],
      "inputStages" : [ "read_orders" ],
      "stages" : [ {
        "name" : "read_orders",
        "display" : {
          "position" : {
            "x" : 240,
            "y" : 0
          }
        },
        "description" : "This Stage obtains the data from SAP.",
        "config" : {
          "type" : ".ReadConfig",
          "failureOutputs" : [ ],
          "reference" : {
            "type" : "Input",
            "name" : "sap_input_next_maintenance_orders_for_work_centers",
            "path" : "",
            "params" : { },
            "connectionName" : "sap_sp"
          },
          "handleGoodNoData" : false,
          "goodNoDataOutputs" : [ ]
        },
        "outputs" : [ "format_array" ]
      }, {
        "name" : "format_array",
        "display" : {
          "position" : {
            "x" : 690,
            "y" : 0
          }
        },
        "description" : "This Stage use JSONata to format the SAP payload.",
        "config" : {
          "type" : ".JSONataTransformConfig",
          "transformExpression" : "$map(event.value.d.results, function($o) {\r\n    $sift($o, function($v, $k) {\r\n        $k != \"__metadata\" and $not($exists($v.__deferred))\r\n    })\r\n})"
        },
        "outputs" : [ "Return" ]
      }, {
        "name" : "Return",
        "display" : {
          "position" : {
            "x" : 1140,
            "y" : 0
          }
        },
        "description" : "",
        "config" : {
          "type" : ".ReturnConfig"
        },
        "outputs" : [ ]
      } ],
      "trackActivity" : false,
      "queueSize" : 10000,
      "triggers" : [ {
        "name" : "callable_trigger",
        "display" : {
          "position" : {
            "x" : -450,
            "y" : 0
          }
        },
        "description" : "This Pipeline is triggered when called from another Intelligence Hub configuration object.",
        "config" : {
          "type" : ".TriggerCallable",
          "enabled" : true,
          "parameters" : {
            "type" : "EmptyParameters"
          }
        }
      } ],
      "errorHandler" : {
        "type" : "default"
      }
    }, {
      "name" : "south_field_mappings_for_lookup",
      "description" : "This Pipeline obtains the system mappings for assets in the South Field.",
      "groupAs" : "/general",
      "tags" : [ "historian3_specialization" ],
      "inputStages" : [ "read_mappings" ],
      "stages" : [ {
        "name" : "return",
        "display" : {
          "position" : {
            "x" : 690,
            "y" : 0
          }
        },
        "description" : "",
        "config" : {
          "type" : ".ReturnConfig"
        },
        "outputs" : [ ]
      }, {
        "name" : "read_mappings",
        "display" : {
          "position" : {
            "x" : 240,
            "y" : 0
          }
        },
        "description" : "The Stage reads the data from the mapping table.",
        "config" : {
          "type" : ".ReadConfig",
          "failureOutputs" : [ ],
          "reference" : {
            "type" : "Input",
            "name" : "postgresql_input_south_field_maintenance_data",
            "path" : "",
            "params" : {
              "assetPath" : null
            },
            "connectionName" : "postgresql_sp"
          },
          "handleGoodNoData" : false,
          "goodNoDataOutputs" : [ ]
        },
        "outputs" : [ "return" ]
      } ],
      "trackActivity" : false,
      "queueSize" : 10000,
      "triggers" : [ {
        "name" : "callable_trigger",
        "display" : {
          "position" : {
            "x" : -450,
            "y" : 0
          }
        },
        "description" : "The Pipeline executes when called by another Intelligence Hub configuration component. ",
        "config" : {
          "type" : ".TriggerCallable",
          "enabled" : true,
          "parameters" : {
            "type" : "EmptyParameters"
          }
        }
      } ],
      "errorHandler" : {
        "type" : "default"
      }
    } ],
    "namespace" : [ ],
    "lookupMap" : [ {
      "name" : "sap_maintenance_orders",
      "tags" : [ "historian3_specialization", "telemetry4_maintenance" ],
      "primaryKey" : "MainWorkCenter",
      "source" : {
        "type" : "dynamic",
        "reference" : {
          "type" : "Pipeline",
          "name" : "sap_maintenance_orders_for_lookup",
          "path" : "",
          "params" : { }
        },
        "expirationInterval" : {
          "duration" : 5,
          "units" : "Minutes"
        }
      }
    }, {
      "name" : "south_field_mappings",
      "description" : "This Lookup Map contains the system mappings for South Field assets.",
      "tags" : [ "historian3_specialization" ],
      "primaryKey" : "path",
      "source" : {
        "type" : "dynamic",
        "reference" : {
          "type" : "Pipeline",
          "name" : "south_field_mappings_for_lookup",
          "path" : "",
          "params" : { }
        },
        "expirationInterval" : {
          "duration" : 5,
          "units" : "Minutes"
        }
      }
    } ],
    "servers" : {
      "i3x" : {
        "historyReadPipeline" : {
          "type" : "Empty"
        },
        "writePipeline" : {
          "type" : "Empty"
        }
      }
    }
  },
  "network" : {
    "groups" : [ ],
    "hubs" : [ ]
  }
}