Skip to content

Commit

Permalink
Merge pull request #125 from GridProtectionAlliance/feature/v4.1.0
Browse files Browse the repository at this point in the history
Added calulation when last value is selected. Modified the links to b…
  • Loading branch information
elwills authored May 30, 2023
2 parents cde71b2 + 72c6b4d commit 4348a51
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 45 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@
- Updated to Grafana plugin SDK v9.4.7
- Fixed PI AF calculation
- Added plugin screenshots

## 4.1.0

- Modified the PI Webapi controller endpoints used when calculation is selected
- Allow calculation when last value option is selected
- When calculation is selected, change label from Interpolated to Interval
- Fixed issue with variable in Element Path
2 changes: 1 addition & 1 deletion dist/module.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/module.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
{"name": "Datasource Configuration", "path": "img/configuration.png"},
{"name": "Annotations Editor", "path": "img/annotations.png"}
],
"version": "4.0.0",
"updated": "2023-05-02"
"version": "4.1.0",
"updated": "2023-05-29"
},
"dependencies": {
"grafanaDependency": ">=8.4.0",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "grid-protection-alliance-osisoftpi-grafana",
"version": "4.0.0",
"version": "4.1.0",
"description": "OSISoft PI Grafana Plugin",
"scripts": {
"build": "grafana-toolkit plugin:build",
Expand Down
31 changes: 23 additions & 8 deletions src/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ export class PiWebAPIDatasource extends DataSourceApi<PIWebAPIQuery, PIWebAPIDat
.then((result: PiwebapiRsp) => [result])
.then(metricQueryTransform)
: ds.getAssetServers().then(metricQueryTransform);
} else if (query.type === 'databases' && !!query.afServerWebId) {
return ds.getDatabases(query.afServerWebId, {}).then(metricQueryTransform);
} else if (query.type === 'databases') {
return ds
.getAssetServer(query.path)
Expand Down Expand Up @@ -718,19 +720,32 @@ export class PiWebAPIDatasource extends DataSourceApi<PIWebAPIQuery, PIWebAPIDat
let url = '';
const isSummary = target.summary && target.summary.types && target.summary.types.length > 0;
const isInterpolated = target.interpolate && target.interpolate.enable;
const isRecorded = target.recordedValues && target.recordedValues.enable;
// perhaps add a check to see if interpolate override time < query.interval
const intervalTime = target.interpolate.interval ? target.interpolate.interval : query.interval;
const timeRange = '?startTime=' + query.range.from.toJSON() + '&endTime=' + query.range.to.toJSON();
const targetName = target.expression || target.elementPath;
const displayName = target.display ? this.templateSrv.replace(target.display, query.scopedVars) : null;
if (target.expression) {
url += '/calculation';
if (isSummary) {
if (target.useLastValue?.enable) {
url += '/times?&time=' + query.range.to.toJSON();
} else if (isSummary) {
url += '/summary' + timeRange + (isInterpolated ? '&sampleType=Interval&sampleInterval=' + intervalTime : '');
} else if (isInterpolated) {
url += '/intervals' + timeRange + '&sampleInterval=' + intervalTime;
} else {
} else if (isRecorded) {
url += '/recorded' + timeRange;
} else {
const windowWidth = 40;
const diff = Math.floor((query.range.to.valueOf() - query.range.from.valueOf()) / windowWidth);
let timeQuery = 'time=' + query.range.from.toJSON();
for (let i = 1; i < windowWidth; i ++) {
const newTime = query.range.from.valueOf() + i * diff;
timeQuery += '&time=' + new Date(newTime).toISOString();
}
timeQuery += '&time=' + query.range.to.toJSON();
url += '/times?' + timeQuery;
}
url += '&expression=' + encodeURIComponent(target.expression.replace(/\${intervalTime}/g, intervalTime));
if (target.attributes.length > 0) {
Expand All @@ -749,18 +764,18 @@ export class PiWebAPIDatasource extends DataSourceApi<PIWebAPIQuery, PIWebAPIDat
}
} else {
url += '/streamsets';
if (isSummary) {
if (target.useLastValue?.enable) {
url += '/value?time=' + query.range.to.toJSON();
} else if (isSummary) {
url += '/summary' + timeRange + '&intervals=' + query.maxDataPoints + this.getSummaryUrl(target.summary);
} else if (isInterpolated) {
url += '/interpolated' + timeRange + '&interval=' + intervalTime;
} else if (target.recordedValues && target.recordedValues.enable) {
} else if (isRecorded) {
const maxNumber =
target.recordedValues.maxNumber && !isNaN(target.recordedValues.maxNumber)
? target.recordedValues.maxNumber
: query.maxDataPoints;
url += '/recorded' + timeRange + '&maxCount=' + maxNumber;
} else if (target.useLastValue?.enable) {
url += '/value?time=' + query.range.to.toJSON();
} else {
url += '/plot' + timeRange + '&intervals=' + query.maxDataPoints;
}
Expand All @@ -782,9 +797,9 @@ export class PiWebAPIDatasource extends DataSourceApi<PIWebAPIQuery, PIWebAPIDat
private handleBatchResponse(response: any, target: any, displayName: string | null): Promise<PiwebapTargetRsp[]> {
const targetName = target.expression || target.elementPath;
const noTemplate = target.elementPathArray.length === 1 && target.elementPath === target.elementPathArray[0].path;
let index = 1;
const totalSize = noTemplate ? target.attributes.length : target.elementPathArray.length;
const targetResults: PiwebapTargetRsp[] = [];
for (const _ of target.attributes) {
for (let index = 1; index <= totalSize; index++) {
const dataKey = `Req${index + 1000}`;
const path = response.config.data[dataKey].Headers ? response.config.data[dataKey].Headers['Asset-Path'] : null;
const data = response.data[dataKey];
Expand Down
70 changes: 38 additions & 32 deletions src/query/QueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,10 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
const ctrl = this;
const findQuery = query.isPiPoint
? { type: 'dataserver' }
: { path: this.getSegmentPathUpTo(currentSegment ?? this.state.segments.slice(0), index) };
: {
path: this.getSegmentPathUpTo(currentSegment ?? this.state.segments.slice(0), index),
afServerWebId: this.state.segments[0].value ? this.state.segments[0].value.webId : undefined,
};

if (!query.isPiPoint) {
if (datasource.afserver?.name && index === 0) {
Expand All @@ -374,10 +377,6 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
},
]);
}

// if (!findQuery.path?.length) {
// return Promise.resolve([]);
// }
}
return datasource
.metricFindQuery(findQuery, Object.assign(data?.request?.scopedVars ?? {}, { isPiPoint: query.isPiPoint }))
Expand Down Expand Up @@ -1060,7 +1059,11 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
)}

<InlineFieldRow>
<InlineField label="Use Last Value" labelWidth={LABEL_WIDTH}>
<InlineField
label="Use Last Value"
tooltip={"Fetch only last value from time range"}
labelWidth={LABEL_WIDTH}
>
<InlineSwitch
value={useLastValue.enable}
onChange={() =>
Expand All @@ -1071,11 +1074,12 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
}
/>
</InlineField>
</InlineFieldRow>

{this.props.datasource.useUnitConfig && (
<InlineFieldRow>
<InlineField label="Use unit from datapoints" labelWidth={LABEL_WIDTH}>
{this.props.datasource.useUnitConfig && (
<InlineField
label="Use unit from datapoints"
tooltip={"Use unit in label from PI tag or PI AF attribute"}
labelWidth={LABEL_WIDTH}
>
<InlineSwitch
value={useUnit.enable}
onChange={() =>
Expand All @@ -1086,28 +1090,30 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
}
/>
</InlineField>
</InlineFieldRow>
)}
)}
</InlineFieldRow>

{!useLastValue.enable && (
<>
<InlineField
label="Calculation"
labelWidth={LABEL_WIDTH}
tooltip={
"Modify all attributes by an equation. Use '.' for current item. Leave Attributes empty if you wish to perform element based calculations."
<InlineFieldRow>
<InlineField
label="Calculation"
labelWidth={LABEL_WIDTH}
tooltip={
"Modify all attributes by an equation. Use '.' for current item. Leave Attributes empty if you wish to perform element based calculations."
}
>
<Input
onBlur={onRunQuery}
value={expression}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
onChange({ ...metricsQuery, expression: event.target.value })
}
>
<Input
onBlur={onRunQuery}
value={expression}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
onChange({ ...metricsQuery, expression: event.target.value })
}
placeholder="'.'*2"
/>
</InlineField>
placeholder="'.'*2"
/>
</InlineField>
</InlineFieldRow>

{!useLastValue.enable && (
<>
<InlineFieldRow>
<InlineField
label="Max Recorded Values"
Expand Down Expand Up @@ -1155,7 +1161,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {

<InlineFieldRow>
<InlineField
label="Interpolate Period"
label={!!expression ? "Interval Period" : "Interpolate Period"}
labelWidth={LABEL_WIDTH}
tooltip={"Override time between sampling, e.g. '30s'. Defaults to timespan/chart width."}
>
Expand All @@ -1168,7 +1174,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
placeholder="30s"
/>
</InlineField>
<InlineField label="Interpolate" labelWidth={LABEL_WIDTH}>
<InlineField label={!!expression ? "Interval Values" : "Interpolate"} labelWidth={LABEL_WIDTH}>
<InlineSwitch
value={interpolate.enable}
onChange={() =>
Expand Down

0 comments on commit 4348a51

Please sign in to comment.