@@ -9,6 +9,11 @@ export interface Signal104 {
9
9
ti : string | null ;
10
10
}
11
11
12
+ interface ExtractSignal104Result {
13
+ signal : Signal104 | null ;
14
+ error ?: string ;
15
+ }
16
+
12
17
enum SignalType {
13
18
Monitor ,
14
19
Control ,
@@ -17,102 +22,81 @@ enum SignalType {
17
22
18
23
const private104Selector = `Private[type="${ PROTOCOL_104_PRIVATE } "]` ;
19
24
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 [ ] = [ ] ;
22
28
const address104Elements = doc . querySelectorAll ( `${ private104Selector } > Address` ) ;
23
29
24
30
address104Elements . forEach ( ( addressElement ) => {
25
- const signal104Data = extractSignal104Data ( addressElement , doc ) ;
31
+ const signal104Result = extractSignal104Data ( addressElement , doc ) ;
26
32
27
- if ( signal104Data ) {
28
- allSignal104Data . push ( signal104Data ) ;
33
+ if ( signal104Result . error ) {
34
+ errors . push ( signal104Result . error ) ;
35
+ } else {
36
+ signals . push ( signal104Result . signal ! ) ;
29
37
}
30
38
} ) ;
31
39
32
- console . log ( address104Elements ) ;
33
-
34
- return allSignal104Data ;
40
+ return { signals, errors } ;
35
41
}
36
42
37
- function extractSignal104Data ( addressElement : Element , doc : XMLDocument ) : Signal104 | null {
43
+ function extractSignal104Data ( addressElement : Element , doc : XMLDocument ) : ExtractSignal104Result {
38
44
const ti = addressElement . getAttribute ( 'ti' ) ;
39
45
const ioa = addressElement . getAttribute ( 'ioa' ) ;
40
46
41
47
// By convention the last four digits of the ioa are the signalnumber, see https://github.com/com-pas/compas-open-scd/issues/334
42
48
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 } ` } ;
45
50
}
46
- const signalNumber = ioa . slice ( - 4 ) ;
51
+ const { signalNumber, bayName } = splitIoa ( ioa ) ;
47
52
48
53
const signalType = getSignalType ( ti ) ;
49
54
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 } ` } ;
52
56
}
53
57
const isMonitorSignal = signalType === SignalType . Monitor ;
54
58
55
- // TODO: Doi desc, Bay name, VoltageLevel name, Substation name
56
-
57
59
addressElement . parentElement ;
58
60
const parentDOI = addressElement . closest ( 'DOI' ) ;
59
61
60
62
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 } ` } ;
63
64
}
64
65
65
66
const doiDesc = parentDOI . getAttribute ( 'desc' ) ;
66
- const parentIED = parentDOI . closest ( 'IED' ) ;
67
- if ( ! parentIED ) {
68
- console . log ( 'No parent IED' ) ;
69
- return null ;
70
- }
71
67
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 ) ;
84
70
85
71
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 } ` } ;
88
73
}
89
74
90
- const bayName = parentBay . getAttribute ( 'name' ) ;
91
75
const parentVoltageLevel = parentBay . closest ( 'VoltageLevel' ) ;
92
76
93
77
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 } ` } ;
96
79
}
97
80
98
81
const voltageLevelName = parentVoltageLevel . getAttribute ( 'name' ) ;
99
82
const parentSubstation = parentVoltageLevel . closest ( 'Substation' ) ;
100
83
101
84
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 } ` } ;
104
86
}
105
87
106
88
const substationName = parentSubstation . getAttribute ( 'name' ) ;
107
89
108
90
const name = `${ substationName } ${ voltageLevelName } ${ bayName } ${ doiDesc } ` ;
109
91
110
92
return {
111
- name,
112
- signalNumber,
113
- isMonitorSignal,
114
- ti,
115
- ioa
93
+ signal : {
94
+ name,
95
+ signalNumber,
96
+ isMonitorSignal,
97
+ ti,
98
+ ioa
99
+ }
116
100
}
117
101
}
118
102
@@ -132,3 +116,12 @@ function getSignalType(tiString: string): SignalType {
132
116
return SignalType . Unknown ;
133
117
}
134
118
}
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