Skip to content

Commit ee4f8f6

Browse files
committed
feat: Adjust bay searching logic and add log events for errors
1 parent 8fab275 commit ee4f8f6

File tree

2 files changed

+60
-52
lines changed

2 files changed

+60
-52
lines changed

packages/plugins/src/menu/Export104.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { LitElement, property } from 'lit-element';
22
import { stringify } from 'csv-stringify/browser/esm/sync';
3+
import { newLogEvent } from '@openscd/core/foundation/deprecated/history.js';
34

45
import { extractAllSignal104Data, Signal104 } from './export104/foundation.js';
56

@@ -18,9 +19,19 @@ export default class Export104 extends LitElement {
1819
];
1920

2021
async run(): Promise<void> {
22+
const { signals, errors } = extractAllSignal104Data(this.doc);
2123

22-
const allSignal104Data = extractAllSignal104Data(this.doc);
23-
const csvLines = this.generateCsvLines(allSignal104Data);
24+
errors.forEach((error) => this.logWarning(error));
25+
26+
if (signals.length === 0) {
27+
this.dispatchEvent(newLogEvent({
28+
kind: 'info',
29+
title: 'Export 104 found no signals',
30+
}));
31+
return;
32+
}
33+
34+
const csvLines = this.generateCsvLines(signals);
2435

2536
const csvContent = stringify(csvLines, {
2637
header: true,
@@ -31,10 +42,14 @@ export default class Export104 extends LitElement {
3142
});
3243

3344
this.downloadCsv(csvBlob);
45+
}
3446

35-
console.log(csvLines);
36-
37-
console.log('Export104', allSignal104Data);
47+
private logWarning(errorMessage: string): void {
48+
this.dispatchEvent(newLogEvent({
49+
kind: 'warning',
50+
title: 'Export 104 found invalid signal',
51+
message: errorMessage,
52+
}));
3853
}
3954

4055
private generateCsvLines(allSignal104Data: Signal104[]): string[][] {

packages/plugins/src/menu/export104/foundation.ts

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export interface Signal104 {
99
ti: string | null;
1010
}
1111

12+
interface ExtractSignal104Result {
13+
signal: Signal104 | null;
14+
error?: string;
15+
}
16+
1217
enum SignalType {
1318
Monitor,
1419
Control,
@@ -17,102 +22,81 @@ enum SignalType {
1722

1823
const private104Selector = `Private[type="${PROTOCOL_104_PRIVATE}"]`;
1924

20-
export function extractAllSignal104Data(doc: XMLDocument): Signal104[] {
21-
const allSignal104Data: Signal104[] = [];
25+
export function extractAllSignal104Data(doc: XMLDocument): { signals: Signal104[], errors: string[] } {
26+
const signals: Signal104[] = [];
27+
const errors: string[] = [];
2228
const address104Elements = doc.querySelectorAll(`${private104Selector} > Address`);
2329

2430
address104Elements.forEach((addressElement) => {
25-
const signal104Data = extractSignal104Data(addressElement, doc);
31+
const signal104Result = extractSignal104Data(addressElement, doc);
2632

27-
if (signal104Data) {
28-
allSignal104Data.push(signal104Data);
33+
if (signal104Result.error) {
34+
errors.push(signal104Result.error);
35+
} else {
36+
signals.push(signal104Result.signal!);
2937
}
3038
});
3139

32-
console.log(address104Elements);
33-
34-
return allSignal104Data;
40+
return { signals, errors };
3541
}
3642

37-
function extractSignal104Data(addressElement: Element, doc: XMLDocument): Signal104 | null {
43+
function extractSignal104Data(addressElement: Element, doc: XMLDocument): ExtractSignal104Result {
3844
const ti = addressElement.getAttribute('ti');
3945
const ioa = addressElement.getAttribute('ioa');
4046

4147
// By convention the last four digits of the ioa are the signalnumber, see https://github.com/com-pas/compas-open-scd/issues/334
4248
if (ti === null || ioa === null || ioa.length < 4) {
43-
console.log('No ti, io or io too short');
44-
return null;
49+
return { signal: null, error: `ti or ioa are missing or ioa is less than 4 digits, ti: ${ti}, ioa: ${ioa}` };
4550
}
46-
const signalNumber = ioa.slice(-4);
51+
const { signalNumber, bayName } = splitIoa(ioa);
4752

4853
const signalType = getSignalType(ti);
4954
if (signalType === SignalType.Unknown) {
50-
console.log('Unknown signal type');
51-
return null;
55+
return { signal: null, error: `Unknown signal type for ti: ${ti}, ioa: ${ioa}` };
5256
}
5357
const isMonitorSignal = signalType === SignalType.Monitor;
5458

55-
// TODO: Doi desc, Bay name, VoltageLevel name, Substation name
56-
5759
addressElement.parentElement;
5860
const parentDOI = addressElement.closest('DOI');
5961

6062
if (!parentDOI) {
61-
console.log('No parent DOI');
62-
return null;
63+
return { signal: null, error: `No parent DOI found for address with ioa: ${ioa}` };
6364
}
6465

6566
const doiDesc = parentDOI.getAttribute('desc');
66-
const parentIED = parentDOI.closest('IED');
67-
if (!parentIED) {
68-
console.log('No parent IED');
69-
return null;
70-
}
7167

72-
const iedName = parentIED.getAttribute('name');
73-
74-
const lNodeQuery = `Substation > VoltageLevel > Bay LNode[iedName="${iedName}"]`;
75-
console.log(lNodeQuery);
76-
const parentLNode = doc.querySelector(lNodeQuery);
77-
78-
if (!parentLNode) {
79-
console.log('No parent LNode');
80-
return null;
81-
}
82-
83-
const parentBay = parentLNode.closest('Bay');
68+
const parentBayQuery = `:root > Substation > VoltageLevel > Bay[name="${bayName}"]`;
69+
const parentBay = doc.querySelector(parentBayQuery);
8470

8571
if (!parentBay) {
86-
console.log('No parent Bay');
87-
return null;
72+
return { signal: null, error: `No bay found with bayname: ${bayName} for ioa ${ioa}` };
8873
}
8974

90-
const bayName = parentBay.getAttribute('name');
9175
const parentVoltageLevel = parentBay.closest('VoltageLevel');
9276

9377
if (!parentVoltageLevel) {
94-
console.log('No parent VL');
95-
return null;
78+
return { signal: null, error: `No parent voltage level found for bay ${bayName} for ioa ${ioa}` };
9679
}
9780

9881
const voltageLevelName = parentVoltageLevel.getAttribute('name');
9982
const parentSubstation = parentVoltageLevel.closest('Substation');
10083

10184
if (!parentSubstation) {
102-
console.log('No parent Substation');
103-
return null;
85+
return { signal: null, error: `No parent substation found for voltage level ${voltageLevelName} for ioa ${ioa}` };
10486
}
10587

10688
const substationName = parentSubstation.getAttribute('name');
10789

10890
const name = `${substationName}${voltageLevelName}${bayName}${doiDesc}`;
10991

11092
return {
111-
name,
112-
signalNumber,
113-
isMonitorSignal,
114-
ti,
115-
ioa
93+
signal: {
94+
name,
95+
signalNumber,
96+
isMonitorSignal,
97+
ti,
98+
ioa
99+
}
116100
}
117101
}
118102

@@ -132,3 +116,12 @@ function getSignalType(tiString: string): SignalType {
132116
return SignalType.Unknown;
133117
}
134118
}
119+
120+
// By Alliander convention the last four digits of the ioa are the signalnumber and the rest is the bay number
121+
// And every bay name consists of "V" + bay number
122+
function splitIoa(ioa: string): { signalNumber: string, bayName: string } {
123+
const signalNumber = ioa.slice(-4);
124+
const bayName = `V${ioa.slice(0, -4)}`;
125+
126+
return { signalNumber, bayName };
127+
}

0 commit comments

Comments
 (0)