Represents the structure of a single analytics algorithm within CMD's information model.
Each field below is pointing to a specific key, with the information about the purpose and possible values. Click on a given section to learn more.
Refer to this wiki page to learn more about the general purpose of information model and to see the concreate examples.
Name under which given algorithm will be referenced within information model file. Same name cannot be repeated within one file!
In most cases it can be equal to path field. There are places, where it's handy to alias same function multiple times (with different inputs), example:
[
{
"name": "StartupsAverage",
"path": "Statistics",
"inputs": [
{
"type": "constant",
"inputName": "function",
"dataType": "stringArray",
"values": [
"Average"
]
},
"rest of the fields is not displayed"
],
"dependencies": [
"InherentAvailabilityDay"
],
"schedule": "day",
"retention": "default"
},
{
"name": "StartupsMedian",
"path": "Statistics",
"inputs": [
{
"type": "constant",
"inputName": "function",
"dataType": "stringArray",
"values": [
"Median"
]
},
"rest of the fields is not displayed"
],
"dependencies": [
"InherentAvailabilityDay"
],
"schedule": "day",
"retention": "default"
}
]
Actual analytics azure function name, which shall be executed by the given algorithm.
Note that in order for the function to be visible by the CMD backend (and information model), docker container with the function code needs to be uploaded to the CMD's container registry.
In practice, it means that code with azure function needs to be merged to the master branch of the CMDFunctions repository.
Representation of the actual algorithm inputs. Shall be provided as an array of objects (dicts); order is not important.
Objects are associated with actual function input by inputName; input type selection is done by type field.
Simple constant value passed as an algorithm input with given data type. Example:
{
"type": "constant",
"dataType": "integer",
"inputName": "temperatureReference",
"value": 40
}
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"constant" Requested value data type. If this filed is not provided, the value data type will be inferred.
Required when datatype field is NOT stringArray. Example:
{
"type": "constant",
"dataType": "string",
"inputName": "trendName",
"value": "PowerTrend"
}
Required when datatype field IS stringArray. Example:
{
"type": "constant",
"datatype": "stringArray",
"inputName": "functions",
"values": [
"min",
"max",
"rms",
"delta",
"std",
"mean"
]
}
Returns value which is calculated by the CMD - refer to specific implementation (defined by calculation field) for more details. Example:
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "FanLifetimeStartDate"
}
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"calculated" Defines actual calculation which will be performed. Actual code can be found here.
Returns capacitor component start date.
Technically, start date for each component is created in CMD's Cosmos DB (docType="ComponentLifetime") at first run of calculation for a given drive. It is determined based on the following logic:
"CapacitorLifetimeStartDate" Returns fan component start date.
Technically, start date for each component is created in CMD's Cosmos DB (docType="ComponentLifetime") at first run of calculation for a given drive. It is determined based on the following logic:
"FanLifetimeStartDate" Returns IGBT component start date.
Technically, start date for each component is created in CMD's Cosmos DB (docType="ComponentLifetime") at first run of calculation for a given drive. It is determined based on the following logic:
"IgbtLifetimeStartDate" Returns drive's nominal current taken from CMD's DriveDimensionMap document (field: maximumContinuousCurrentA), based on the drive's type code (shortTypeCode field in DriveRegistrationInfo document).
This method can be used for ACS800 drives - other drive types are not included in lookup table.
DriveDimensionMap document has following form:
{
"id": "2E35FA40-CE65-4F17-98E0-8AAD445ED613",
"partitionKey": "global",
"docType": "DriveDimensionMap",
"rules": [
{
"typeCode": "ACS800-01-0001-2",
"maximumContinuousCurrentA": "5.1",
"maximumCurrentA": "6.5",
"maximumContinousPowerKw": "1.1",
"frameSize": "R2",
"driveType": "SingleDrive"
},
{
"typeCode": "ACS800-01-0002-2",
"maximumContinuousCurrentA": "6.5",
"maximumCurrentA": "8.2",
"maximumContinousPowerKw": "1.5",
"frameSize": "R2",
"driveType": "SingleDrive"
}
"skipped remaining entries"
]
}
"NominalCurrentFromLookUpTable" Returns drive's nominal current taken from the drive type code. Type code is taken from CMD's DriveRegistrationInfo document, field: shortTypeCode. Can be used for newer drives, e.g. ACS880 - older drives don't have current encoded in type code, thous this method will not work.
For example, for following type code: "ACS880-01-032A-3", returned value will be equal to 32.
Specific value:"NominalCurrentFromTypeCode" Returns internal drive signal (timeseries), referenced by symbolic_name. Signal will be truncated based on the algorithm schedule, e.g. if hourly schedule is requested, input signal will be starting at the beginning of the given hour and spawning to the end of the hour.
Example:
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp",
}
There are cases where it is possible (and allowed) that input signal will be missing. For example, when algorithm is expecting multiple signals, and, based on the signal availability, final signal, which will be passed to the calculations, is selected. In this case, optional flag is necessary; otherwise error will be raised in case of missing signal.
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"signal" Selects the actual drive timeseries signal which will be feed to the algorithm. Signal mapping and list of all available drive signals is located within abb.drives.{drive_type}.{type_id}.json file, section variables (stored in information model repo). Provided symbolicName shall match symbolicName field defined in this file.
Example snipped from drive signal mapping file:
{
"skipped beginning sections",
"variables": {
"01_02": {
"description": "SPEED (rpm)",
"unit": "rpm",
"dataType": "number",
"symbolicName": "motor_speed",
"textKey": "ABB.CMD.Backend.KPI.Parameters.acs800_asxr_as7r.01_02"
},
"01_03": {
"description": "FREQUENCY (Hz)",
"unit": "Hz",
"dataType": "number",
"symbolicName": "frequency_hz",
"textKey": "ABB.CMD.Backend.KPI.Parameters.acs800.Frequency"
},
"skipped rest of the mapping and end sections"
}
}
Returns external sensor signal (timeseries), referenced by symbolic_name. Signal will be truncated based on the algorithm schedule, e.g. if hourly schedule is requested, input signal will be starting at the beginning of the given hour and spawning to the end of the hour.
In practice, the used sensor will be a Yocto-Meteo device, which supports the following signals:
Example:
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
}
Since not all drives have an external sensor mounted, the optional flag is especially important for the sensor signal. Refer to the optional field description for more information.
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"signalSensor" Selects the actual sensor timeseries signal which will be feed to the algorithm. Signal mapping and list of all available sensor signals is located within abb.drives.sensor.json file, section variables.
In practice, for external sensor, following values are supported for symbolicName:
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"events" Returns output from the other algorithm, defined in the information model file. This way, we can chain algorithms into sequences, where one algorithm output is an input for a different algorithm.
timeRange field controls the amount of the results which will be provided to the algorithm. Note that algorithms are referenced by name, not path field (actual azure function name).
Examples:
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "CapacitorLifetimeConsumptionHour",
"property": "consumedLifetime",
"timeRange": "day"
}
{
"type": "AlgorithmOutput",
"inputName": "remainingStack",
"algorithm": "IgbtPowerCycleHour",
"property": "remainingValues",
"timerange": "previousHourSameDay",
"optional": true
}
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"AlgorithmOutput" name of the algorithm which will be a source of the results. Algorithm definition with name shall be defined within information model file.
Selects the provided key in algorithm output dictionary.
Expected response from analytics azure function has the following form:
{
"details": {
"key 1": 1,
"key 2": "value 2"
},
"status": "response status",
"message": "response message if exists",
"version": "azure function version"
}
property allows to select key from the details dictionary. For example, by setting property="key 2", "value 2" will be passed to the azure function input.
If property is not provided, whole details dictionary will be passed as an input to the azure function.
Allows to select results from the required time range, and passing them as an algorithm input. For more information, refer to the description of the specific value.
Be careful with using this setting - in most cases it is not necessary!
Selects ALL results which are available in CMD's database for a given algorithm.
Currently this setting is NOT used by any algorithm.
Specific value:"all" Same as day - see day description.
"default" Returns result from previous hour on the same day. If previous hour has no result, latest hour with results will be used instead.
Note that this setting make sense for algorithms, which are working on hourly schedule (to select previous calculation result).
Example:
[
{
"name": "IgbtPowerCycleHour",
"path": "IgbtPowerCycleHour",
"inputs": [
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "igbt_junction_temp",
},
{
"type": "constant",
"datatype": "integer",
"inputName": "preventiveLifetimeYears",
"value": 25
},
{
"type": "constant",
"inputName": "igbtType",
"dataType": "string",
"value": "Infineon_IGBT3"
},
{
"type": "AlgorithmOutput",
"inputName": "remainingStack",
"algorithm": "IgbtPowerCycleHour",
"property": "remainingValues",
"timerange": "previousHourSameDay",
"optional": true
}
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
remainingStack input is set to previousHourSameDay to also use results from previous algorithm execution. Note that optional flag is also used - without it, first execution of the day would produce an error since previous result is not yet present (and in consequence, this error will be propagated to next executions also).
"previousHourSameDay" Returns the results from the current day, when the algorithm calculations where requested.
Consider the following example:
[
{
"name": "AggregateLifetimeDailyFan",
"path": "AggregateLifetimeDaily",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "FanLifetimeConsumptionHour",
"property": "consumedLifetime",
"timeRange": "day"
},
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "FanLifetimeStartDate"
},
{
"type": "constant",
"datatype": "string",
"inputName": "algorithm",
"value": "FanLifetimeConsumptionHour"
}
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "FanLifetimeConsumptionHour",
"path": "FanLifetimeConsumptionHour",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
AggregateLifetimeDailyFan is using daily results from FanLifetimeConsumptionHour, which is scheduled to be executed every hour. As a result, array of 24 floats will be passed to consumedLifetimesHourly input (note that we are also using property selector and format is not set):
[0.23, 0.52, 0.23, "remaining values skipped"]
"day" Works similarly as day, but selects results from the previous day (compared to when algorithm execution was requested).
For example if algorithm execution was requested on 10-01-2023 12:13, previousDay setting will select the results from 09-01-2023 00:00 to 09-01-2023 23:59.
"previousDay" Returns results from the last 30 days. Example:
[
{
"name": "ThermalAnomalyThirtyDaysAverage",
"path": "Statistics",
"inputs": [
{
"type": "constant",
"datatype": "string",
"inputName": "function",
"value": "Average"
},
{
"type": "AlgorithmOutput",
"inputName": "data",
"algorithm": "ThermalAnomalyDay",
"property": "anomalyDrThermalCPA",
"timeRange": "thirtyDays"
}
],
"dependencies": [
"ThermalAnomalyDay"
],
"schedule": "day",
"retention": "default"
},
{
"name": "ThermalAnomalyDay",
"path": "ThermalAnomalyDay",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "default"
}
]
For data input of ThermalAnomalyThirtyDaysAverage algorithm, we are passing results of ThermalAnomalyDay algorithm from the last 30 days. Since ThermalAnomalyDay is scheduled to be executed daily, data input will be an array of 30 floats.
"thirtyDays" Returns the algorithm results from the current month (compared to when algorithm execution was requested).
For example if algorithm execution was requested on 10-01-2023 12:13, calendarMonth setting will select the results from 01-01-2023 00:00 to 31-01-2023 23:59.
"calendarMonth" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceCapacitorLifetimeStart" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceFanLifetimeStart" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceIgbtLifetimeStart" Returns the latest result before the day for which algorithm calculation was requested.
For example if algorithm execution was requested on 10-01-2023 12:13, latestValue setting will select last available algorithm result before 09-01-2023 23:59.
Currently, no algorithm is using this setting.
Specific value:"latestValue" Functionality used in next level CBM.
Returns maintenance plan associated with the given drive. algorithm input is not important in this case, but still needs to be present.
Example definition in information model:
{
"name": "GraphPointsPMKits",
"path": "GraphPointsPMKits",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "extensionFactors",
"algorithm": "LifetimeExtensionFactorMonthly",
"property": "extension_factor",
"format": "dateAndValue",
"timerange": "all"
},
{
"type": "AlgorithmOutput",
"inputName": "maintenancePlan",
"algorithm": "maintenancePlan",
"timeRange": "maintainancePlan"
}
],
"dependencies": ["LifetimeExtensionFactorMonthly"],
"schedule": "day",
"retention": "latest"
}
Output structure:
{
"SerialNumber": "1140102007",
"ManufacturingDate": "2013-12-30T00:00:00+00:00",
"DeliveryDate": "2014-01-02T00:00:00+00:00",
"CommissioningDate": null,
"ServiceRecommended":
[
{
"Name": "PM9",
"Date": "2023-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
},
{
"Name": "PM12",
"Date": "2026-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
},
{
"Name": "PM18",
"Date": "2032-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
}
],
"ServiceEvents":
[
{
"Date": "2019-06-06T11:40:26.847+00:00",
"Type": "Site update"
},
{
"Date": "2016-06-10T15:05:21.043+00:00",
"Type": "Drive QR code data"
}
]
}
"maintainancePlan" Specifies the desired format of the AlgorithmOutput input.
Results will be passed as a list of objects (dictionaries) without any additional transformation. If this is the desired behaviour, format field shall not be specified.
Example:
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "IgbtThermalCycleHour",
"property": "consumedLifetime",
"timeRange": "day"
}
Will fetch the consumedLifetime key from each result within this day and form the following input:
[0.032, 0.022, 0.012, "remaining values skipped"]
"default" Will attach the date to each result value, creating the input in the following form:
[{"date": "date in 'yyyy-MM-dd'", "value": "actual value"}, {"..."}]
For example:
[{"date": "2022-01-12", "value": 0.0304}, {"date": "2022-01-13", "value": 0.045}, {"..."}]
Used currently in GraphPoints algorithms, example:
{
"name": "GraphPoints_Fan",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "FanLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyFan",
"property": "consumedLifetime",
"timeRange": "dailySinceFanLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyFan"
],
"schedule": "day",
"retention": "latest"
}
"dateAndValue" Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"AlgorithmOutputStatus" Allows to select results from the required time range, and passing them as an algorithm input. For more information, refer to the description of the specific value.
Be careful with using this setting - in most cases it is not necessary!
Selects ALL results which are available in CMD's database for a given algorithm.
Currently this setting is NOT used by any algorithm.
Specific value:"all" Same as day - see day description.
"default" Returns result from previous hour on the same day. If previous hour has no result, latest hour with results will be used instead.
Note that this setting make sense for algorithms, which are working on hourly schedule (to select previous calculation result).
Example:
[
{
"name": "IgbtPowerCycleHour",
"path": "IgbtPowerCycleHour",
"inputs": [
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "igbt_junction_temp",
},
{
"type": "constant",
"datatype": "integer",
"inputName": "preventiveLifetimeYears",
"value": 25
},
{
"type": "constant",
"inputName": "igbtType",
"dataType": "string",
"value": "Infineon_IGBT3"
},
{
"type": "AlgorithmOutput",
"inputName": "remainingStack",
"algorithm": "IgbtPowerCycleHour",
"property": "remainingValues",
"timerange": "previousHourSameDay",
"optional": true
}
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
remainingStack input is set to previousHourSameDay to also use results from previous algorithm execution. Note that optional flag is also used - without it, first execution of the day would produce an error since previous result is not yet present (and in consequence, this error will be propagated to next executions also).
"previousHourSameDay" Returns the results from the current day, when the algorithm calculations where requested.
Consider the following example:
[
{
"name": "AggregateLifetimeDailyFan",
"path": "AggregateLifetimeDaily",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "FanLifetimeConsumptionHour",
"property": "consumedLifetime",
"timeRange": "day"
},
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "FanLifetimeStartDate"
},
{
"type": "constant",
"datatype": "string",
"inputName": "algorithm",
"value": "FanLifetimeConsumptionHour"
}
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "FanLifetimeConsumptionHour",
"path": "FanLifetimeConsumptionHour",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
AggregateLifetimeDailyFan is using daily results from FanLifetimeConsumptionHour, which is scheduled to be executed every hour. As a result, array of 24 floats will be passed to consumedLifetimesHourly input (note that we are also using property selector and format is not set):
[0.23, 0.52, 0.23, "remaining values skipped"]
"day" Works similarly as day, but selects results from the previous day (compared to when algorithm execution was requested).
For example if algorithm execution was requested on 10-01-2023 12:13, previousDay setting will select the results from 09-01-2023 00:00 to 09-01-2023 23:59.
"previousDay" Returns results from the last 30 days. Example:
[
{
"name": "ThermalAnomalyThirtyDaysAverage",
"path": "Statistics",
"inputs": [
{
"type": "constant",
"datatype": "string",
"inputName": "function",
"value": "Average"
},
{
"type": "AlgorithmOutput",
"inputName": "data",
"algorithm": "ThermalAnomalyDay",
"property": "anomalyDrThermalCPA",
"timeRange": "thirtyDays"
}
],
"dependencies": [
"ThermalAnomalyDay"
],
"schedule": "day",
"retention": "default"
},
{
"name": "ThermalAnomalyDay",
"path": "ThermalAnomalyDay",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "default"
}
]
For data input of ThermalAnomalyThirtyDaysAverage algorithm, we are passing results of ThermalAnomalyDay algorithm from the last 30 days. Since ThermalAnomalyDay is scheduled to be executed daily, data input will be an array of 30 floats.
"thirtyDays" Returns the algorithm results from the current month (compared to when algorithm execution was requested).
For example if algorithm execution was requested on 10-01-2023 12:13, calendarMonth setting will select the results from 01-01-2023 00:00 to 31-01-2023 23:59.
"calendarMonth" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceCapacitorLifetimeStart" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceFanLifetimeStart" Returns results between CBM algorithm startDate (see inputs -> Calculated -> calculation -> FanLifetimeStartDate to learn how startDate is determined) and the end of the current (when algorithm execution was requested) day.
Currently, this time range is used only for CBM's GraphPoints algorithm, example:
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
"dailySinceIgbtLifetimeStart" Returns the latest result before the day for which algorithm calculation was requested.
For example if algorithm execution was requested on 10-01-2023 12:13, latestValue setting will select last available algorithm result before 09-01-2023 23:59.
Currently, no algorithm is using this setting.
Specific value:"latestValue" Functionality used in next level CBM.
Returns maintenance plan associated with the given drive. algorithm input is not important in this case, but still needs to be present.
Example definition in information model:
{
"name": "GraphPointsPMKits",
"path": "GraphPointsPMKits",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "extensionFactors",
"algorithm": "LifetimeExtensionFactorMonthly",
"property": "extension_factor",
"format": "dateAndValue",
"timerange": "all"
},
{
"type": "AlgorithmOutput",
"inputName": "maintenancePlan",
"algorithm": "maintenancePlan",
"timeRange": "maintainancePlan"
}
],
"dependencies": ["LifetimeExtensionFactorMonthly"],
"schedule": "day",
"retention": "latest"
}
Output structure:
{
"SerialNumber": "1140102007",
"ManufacturingDate": "2013-12-30T00:00:00+00:00",
"DeliveryDate": "2014-01-02T00:00:00+00:00",
"CommissioningDate": null,
"ServiceRecommended":
[
{
"Name": "PM9",
"Date": "2023-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
},
{
"Name": "PM12",
"Date": "2026-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
},
{
"Name": "PM18",
"Date": "2032-01-02T00:00:00+00:00",
"IsServiceDone": false,
"ServiceDone": null
}
],
"ServiceEvents":
[
{
"Date": "2019-06-06T11:40:26.847+00:00",
"Type": "Site update"
},
{
"Date": "2016-06-10T15:05:21.043+00:00",
"Type": "Drive QR code data"
}
]
}
"maintainancePlan" Returns value from drive's parameter backup file.
Example parameter backup file:
[NETA-21 DDCS Report File]
2022-04-30T22:00:11+00:00
ACS 800 KR1620_SC1 {0}{1}
Application, Properties
DDCS adapter version 3.28.0.0
Name AMAR7320
Version AMXR7320
Parameters, 01: ACTUAL SIGNALS
NAME VALUE MINIMUM MAXIMUM
01.01: MOTOR SPEED FILT [rpm] 478.415405
01.02: SPEED ESTIMATED [rpm] 479.998474
01.03: SPEED MEASURED [rpm] 0.000000 -9999.998047 9999.996094
01.04: MOTOR SPEED [rpm] 479.842346
01.05: FREQUENCY [Hz] 24.008690 -500.000000 499.999939
(skipped rest of the file)
symbolicName will select the proper parameter and, after dispatching to actual id of the parameter, associated VALUE will be returned. For example, for symbolicName="motor_speed", which dispatches to id="01.04", value 479.842346 will be returned.
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"value" Selects the actual drive parameter which will be feed to the algorithm. Parameter mapping is located within abb.drives.{drive_type}.{type_id}.json file, section variables (stored in information model repo). Provided symbolicName shall match symbolicName field defined in this file.
Example snipped from drive signal mapping file:
{
"skipped beginning sections",
"variables": {
"01_02": {
"description": "SPEED (rpm)",
"unit": "rpm",
"dataType": "number",
"symbolicName": "motor_speed",
"textKey": "ABB.CMD.Backend.KPI.Parameters.acs800_asxr_as7r.01_02"
},
"01_03": {
"description": "FREQUENCY (Hz)",
"unit": "Hz",
"dataType": "number",
"symbolicName": "frequency_hz",
"textKey": "ABB.CMD.Backend.KPI.Parameters.acs800.Frequency"
},
"skipped rest of the mapping and end sections"
}
}
Associates input with actual azure function input. inputName shall be provided in camelCase notation. Example:
{
"inputName": "preventiveLifetimeYears",
"type": "actual input type",
"other fields are depending on the input type"
}
Boolean flag which indicates if the input shall be optional. If set to false (default), and if given input is missing (eg. requested drive signal cannot be found), CMD will generate error at payload preparation stage. This is, in most cases, the desired behaviour.
There are scenarios, however, when setting optional flag to true is beneficial. For example, for the following algorithm definition:
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs": [
{
"type": "signalSensor",
"inputName": "sensorTemperature",
"symbolicName": "temperature",
"optional": true
},
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
"remaining inputs omitted"
],
"dependencies": [],
"schedule": "...",
"retention": "..."
}
We are using external sensor temperature, "inputName": "sensorTemperature", with the optional flag. It means that even if drive doesn't have external sensor mounted, and therefore, requested signal doesn't exist, function will still be called with sensorTemperature = null.
If, however, ctrl_board_temp signal cannot be found, the analytics function will NOT be called - CMD will generate an error during payload preparation.
"DCVoltage" ToDo Defines the output format for the analytics library
"GraphPointArray" "EventGroup" Defines which algorithms need to be executed BEFORE running this algorithm. Proper use of dependencies allows you to guarantee the correct execution order within algorithms that are running on the same schedule (e.g. daily). If the algorithm needs results from the current execution of a different algorithm, then dependencies shall be used.
Consider the following case, where dependencies are necessary to guarantee proper execution order:
[
{
"name": "ThermalAnomalyThirtyDaysAverage",
"path": "Statistics",
"inputs":
[
{
"type": "constant",
"datatype": "string",
"inputName": "function",
"value": "Average"
},
{
"type": "AlgorithmOutput",
"inputName": "data",
"algorithm": "ThermalAnomalyDay",
"property": "anomalyDrThermalCPA",
"timeRange": "thirtyDays"
}
],
"dependencies":
[
"ThermalAnomalyDay"
],
"schedule": "day",
"retention": "default"
},
{
"name": "ThermalAnomalyDay",
"path": "ThermalAnomalyDay",
"inputs":
[
"inputs skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "default"
}
]
ThermalAnomalyThirtyDaysAverage consumes current result of ThermalAnomalyDay execution - we need to ensure that ThermalAnomalyDay will be executed first and its results will be ready when ThermalAnomalyThirtyDaysAverage will be executed. Therefore, it's necessary to set dependencies of ThermalAnomalyThirtyDaysAverage to ["ThermalAnomalyDay"].
Dependencies, however, should not be used to describe the relationship between the algorithms. In other words, if one algorithm is expecting the results from the other algorithm as input, it doesn't always mean that adding this information as dependencies is necessary. In the following cases dependencies shall NOT be used:
schedule - in this case the problem of guaranteeing the order of execution is not present, because algorithms are run in different execution batches (e.g. hourly or daily):[
{
"name": "AggregateLifetimeDailyCapacitor",
"path": "AggregateLifetimeDaily",
"inputs":
[
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "CapacitorLifetimeConsumptionHour",
"property": "consumedLifetime",
"timeRange": "day"
},
"other inputs skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "CapacitorLifetimeConsumptionHour",
"path": "CapacitorLifetimeConsumptionHour",
"inputs":
[
"inputs skipped"
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
schedule, but top level algorithm is NOT using the results from the current round of execution. An example of such a situation is algorithm self-referencing, when the algorithm uses results from its previous execution. In that case, necessary results are already existing in the database, so usage of dependencies is not needed: {
"name": "IgbtPowerCycleHour",
"path": "IgbtPowerCycleHour",
"inputs":
[
{
"type": "AlgorithmOutput",
"inputName": "remainingStack",
"algorithm": "IgbtPowerCycleHour",
"property": "remainingValues",
"timerange": "previousHourSameDay",
"optional": true
},
"other inputs skipped"
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
Requested algorithm schedule - interval between the consecutive runs of the same algorithm for the same drive. Decides how often algorithm will be run, but also which snipped of the timeseries signal (internal or external) will be passed to the algorithm if requested.
For example, in the following case:
{
"name": "EnvironmentalAir",
"path": "EnvironmentalAir",
"inputs": [
{
"type": "signal",
"inputName": "temperature",
"symbolicName": "ctrl_board_temp"
},
{
"type": "signal",
"inputName": "igbtCaseTemperature",
"symbolicName": "igbt_case_temp"
}
],
"dependencies": [],
"schedule": "hour",
"retention": "default"
}
Algorithm is running on hourly schedule. If algorithm execution is requested at 10-01-2023 14:48, signals passed as an inputs will be truncated to the range: <10-01-2023 14:00; 10-01-2023 14:59>. Actual number of samples which will be passed to the input depends on the sampling rate and cannot be set/modified by the algorithm.
Defines the lifetime of a Cosmos DB document with algorithm results. In the vast majority of cases, retention shall be set to default. Known exceptions are:
unlimited and latestsevenDaysThis value shall be used in majority of the algorithms. CMD will manage the document in this case - for reporting purposes, this is the desired behaviour.
Specific value:"default" Results will be kept forever, for an unlimited amount of time. This setting shall be used only when you are sure that results will be used also in the future.
Currently, the only example where this behavior is desired is daily lifetime calculations for CBM - in order to calculate the CBM graph (using the GraphPoints algorithm) ALL daily results are taken into account. Example:
[
{
"name": "AggregateLifetimeDailyCapacitor",
"path": "AggregateLifetimeDaily",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
]
"unlimited" Functionality used in next level CBM.
Only one result will be kept for the algorithm per calendar month - new calculations will NOT create new database document, but update existing document (result) for this calendar month.
Consider following algorithm:
{
"name": "AggregatePMKitsHistogramsMonthly",
"path": "AggregatePMKitsHistograms",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "histograms",
"algorithm": "PreventiveMaintenanceKitsHistogramDaily",
"property": "histogram",
"timerange": "calendarMonth"
}
],
"dependencies": ["PreventiveMaintenanceKitsHistogramDaily"],
"schedule": "day",
"retention": "unlimitedPerMonth"
}
Algorith is scheduled to be executed every day, so each day new result will be calculated. At each point in time, however, only one result will be stored in the database per calendar month. So, at first day of the month, new document with the results will be created. During that month each execution of the algorithm will update mentioned document - which also means that previous result (for this month) will be lost.
"unlimitedPerMonth" Only most recent algorithm result document will be kept for a given drive. This behaviour is desired when only most recent result is important, and previous can be removed.
Currently, this setting is used for GraphPoints algorithms - in this case we are every day updating graph results by taking into account new daily component lifetime. Once new graph points are computed, previous are not needed anymore. Example:
[
{
"name": "AggregateLifetimeDailyCapacitor",
"path": "AggregateLifetimeDaily",
"inputs": [
"inputs are skipped"
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "GraphPoints_Capacitor",
"path": "GraphPoints",
"outputFormat": "GraphPointArray",
"inputs": [
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "CapacitorLifetimeStartDate"
},
{
"type": "AlgorithmOutput",
"inputName": "stress",
"algorithm": "AggregateLifetimeDailyCapacitor",
"property": "consumedLifetime",
"timeRange": "dailySinceCapacitorLifetimeStart",
"format": "dateAndValue"
}
],
"dependencies": [
"AggregateLifetimeDailyCapacitor"
],
"schedule": "day",
"retention": "latest"
}
]
"latest" Result document will be kept for 7 days, after that period it will be removed. This setting can be used in case of aggregations - where intermediate results (e.g. hourly) are not needed once aggregate (e.g. daily) is calculated.
Example of such behaviour is daily lifetime aggregate for CBM. Consider the following example:
[
{
"name": "AggregateLifetimeDailyFan",
"path": "AggregateLifetimeDaily",
"inputs": [
{
"type": "AlgorithmOutput",
"inputName": "consumedLifetimesHourly",
"algorithm": "FanLifetimeConsumptionHour",
"property": "consumedLifetime",
"timeRange": "day"
},
{
"type": "calculated",
"inputName": "commissioningDate",
"calculation": "FanLifetimeStartDate"
},
{
"type": "constant",
"datatype": "string",
"inputName": "algorithm",
"value": "FanLifetimeConsumptionHour"
}
],
"dependencies": [],
"schedule": "day",
"retention": "unlimited"
},
{
"name": "FanLifetimeConsumptionHour",
"path": "FanLifetimeConsumptionHour",
"inputs": [
"inputs skipped"
],
"dependencies": [],
"schedule": "hour",
"retention": "sevenDays"
}
]
FanLifetimeConsumptionHour results are needed only as AggregateLifetimeDailyFan input - therefore retention can be set to sevenDays. Notice that in this case you won't have access for hourly results, even for report purposes.
"sevenDays"