@@ -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+
1217enum SignalType {
1318 Monitor ,
1419 Control ,
@@ -17,102 +22,81 @@ enum SignalType {
1722
1823const 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