@@ -104,6 +104,48 @@ type CdcDescription = {
104104
105105export type LNodeDescription = Record < string , CdcDescription > ;
106106
107+ export const supportedCdc = [
108+ "ACD" ,
109+ "ACT" ,
110+ "APC" ,
111+ "ASG" ,
112+ "BAC" ,
113+ "BCR" ,
114+ "BSC" ,
115+ "CMV" ,
116+ "DEL" ,
117+ "DPC" ,
118+ "DPL" ,
119+ "HDEL" ,
120+ "HMV" ,
121+ "HST" ,
122+ "HWYE" ,
123+ "INC" ,
124+ "INS" ,
125+ "ISC" ,
126+ "LPL" ,
127+ "MV" ,
128+ "ORG" ,
129+ "ORS" ,
130+ "SAV" ,
131+ "SEC" ,
132+ "SEQ" ,
133+ "SPC" ,
134+ "SPG" ,
135+ "SPS" ,
136+ "TCS" ,
137+ "TSG" ,
138+ "VSG" ,
139+ "VSS" ,
140+ "WYE" ,
141+ ] as const ;
142+ const cdcTag = new Set < string > ( supportedCdc ) ;
143+ export type SCLTag = ( typeof supportedCdc ) [ number ] ;
144+
145+ export function isSupportedCdc ( cdc : string ) : cdc is SCLTag {
146+ return cdcTag . has ( cdc ) ;
147+ }
148+
107149export type NameSpaceDescription = {
108150 "72" ?: XMLDocument ;
109151 "73" ?: XMLDocument ;
@@ -123,7 +165,7 @@ const defaultDoc81 = new DOMParser().parseFromString(nsd81, "application/xml");
123165
124166/** A utility function that returns a JSON containing the structure of a logical node class
125167 * as described in the IEC 61850-7-4 and IEC 61850-7-420 as JSON
126- * @param lnClass the logical node class to be constructed
168+ * @param lnClassOrCdc the logical node class to be constructed
127169 * @param nsds user defined NSD files defaulting to
128170 * 8-1: 2003A2
129171 * 7-4: 2007B3
@@ -133,19 +175,13 @@ const defaultDoc81 = new DOMParser().parseFromString(nsd81, "application/xml");
133175 * @returns A JSON object represeting NSD information of a logical node
134176 */
135177export function nsdToJson (
136- lnClass : string ,
178+ lnClassOrCdc : string ,
137179 nsds ?: NameSpaceDescription ,
138- ) : LNodeDescription | undefined {
180+ ) : LNodeDescription | CdcChildren | undefined {
181+
139182 const doc74 = nsds && nsds [ "74" ] ? nsds [ "74" ] : defaultDoc74 ;
140183 const doc7420 = nsds && nsds [ "7420" ] ? nsds [ "7420" ] : defaultDoc7420 ;
141- const nsdLnClass74 = doc74 . querySelector ( `LNClass[name="${ lnClass } "]` ) ;
142- const nsdLnClass7420 = doc7420 . querySelector ( `LNClass[name="${ lnClass } "]` ) ;
143-
144- const nsdLnClass = nsdLnClass74 || nsdLnClass7420 ;
145- if ( ! nsdLnClass ) return undefined ;
146-
147- const lnClassJson : LNodeDescription = { } ;
148-
184+
149185 function getServiceConstructedAttributes (
150186 serviceDataAttribute : Element ,
151187 ) : Element [ ] {
@@ -161,18 +197,23 @@ export function nsdToJson(
161197 ) ;
162198 }
163199
164- function getServiceDataAttributes ( dataObject : Element ) : Element [ ] {
200+ function getServiceDataAttributesType ( type : string | null ) : Element [ ] {
165201 const doc81 = nsds && nsds [ "81" ] ? nsds [ "81" ] : defaultDoc81 ;
166202
167- const type = dataObject . getAttribute ( "type" ) ;
168203 return Array . from (
169204 doc81
170205 . querySelector ( `ServiceCDCs > ServiceCDC[cdc="${ type } "]` )
171206 ?. querySelectorAll ( "ServiceDataAttribute" ) ?? [ ] ,
172207 ) ;
173208 }
174209
175- function getSubDataAttributesType ( type : string ) : Element [ ] {
210+ function getServiceDataAttributes ( dataObject : Element ) : Element [ ] {
211+ const type = dataObject . getAttribute ( "type" ) ;
212+
213+ return getServiceDataAttributesType ( type ) ;
214+ }
215+
216+ function getSubDataAttributesType ( type : string | null ) : Element [ ] {
176217 const doc73 = nsds && nsds [ "73" ] ? nsds [ "73" ] : defaultDoc73 ;
177218 const doc72 = nsds && nsds [ "72" ] ? nsds [ "72" ] : defaultDoc72 ;
178219
@@ -190,27 +231,14 @@ export function nsdToJson(
190231 }
191232
192233 function getSubDataAttributes ( dataAttribute : Element ) : Element [ ] {
193- const doc73 = nsds && nsds [ "73" ] ? nsds [ "73" ] : defaultDoc73 ;
194- const doc72 = nsds && nsds [ "72" ] ? nsds [ "72" ] : defaultDoc72 ;
195-
196234 const type = dataAttribute . getAttribute ( "type" ) ;
197- return Array . from (
198- doc73
199- . querySelector ( `ConstructedAttribute[name="${ type } "]` )
200- ?. querySelectorAll ( ":scope > SubDataAttribute" ) ?? [ ] ,
201- ) . concat (
202- Array . from (
203- doc72
204- . querySelector ( `ConstructedAttribute[name="${ type } "]` )
205- ?. querySelectorAll ( ":scope > SubDataAttribute" ) ?? [ ] ,
206- ) ,
207- ) ;
235+
236+ return getSubDataAttributesType ( type )
208237 }
209238
210- function getDataAttributes ( dataObject : Element ) : Element [ ] {
239+ function getDataAttributesType ( type : string | null ) : Element [ ] {
211240 const doc73 = nsds && nsds [ "73" ] ? nsds [ "73" ] : defaultDoc73 ;
212241
213- const type = dataObject . getAttribute ( "type" ) ;
214242 if (
215243 [ "CSG" , "CURVE" , "ENG" , "ING" , "ASG" , "SPG" , "TSG" , "VSG" ] . includes (
216244 `${ type } ` ,
@@ -228,16 +256,28 @@ export function nsdToJson(
228256 ) ;
229257 }
230258
231- function getSubDataObjects ( dataObject : Element ) : Element [ ] {
232- const doc73 = nsds && nsds [ "73" ] ? nsds [ "73" ] : defaultDoc73 ;
259+ function getDataAttributes ( dataObject : Element ) : Element [ ] {
233260 const type = dataObject . getAttribute ( "type" ) ;
261+
262+ return getDataAttributesType ( type ) ;
263+ }
264+
265+ function getSubDataObjectsType ( type : string | null ) : Element [ ] {
266+ const doc73 = nsds && nsds [ "73" ] ? nsds [ "73" ] : defaultDoc73 ;
267+
234268 return Array . from (
235269 doc73
236270 . querySelector ( `CDC[name="${ type } "]` )
237271 ?. querySelectorAll ( "SubDataObject" ) ?? [ ] ,
238272 ) ;
239273 }
240274
275+ function getSubDataObjects ( dataObject : Element ) : Element [ ] {
276+ const type = dataObject . getAttribute ( "type" ) ;
277+
278+ return getSubDataObjectsType ( type )
279+ }
280+
241281 function getDataObjects ( lnClass : Element ) : Element [ ] {
242282 const baseClass = lnClass . ownerDocument . querySelector (
243283 `AbstractLNClass[name="${ lnClass . getAttribute ( "base" ) } "]` ,
@@ -579,11 +619,51 @@ export function nsdToJson(
579619 return data ;
580620 }
581621
582- getDataObjects ( nsdLnClass ) . forEach ( ( dataObject ) => {
583- const name = dataObject . getAttribute ( "name" ) ! ;
622+ function CdcChildren ( type : string ) : CdcChildren {
623+
624+ const children : CdcChildren = { } ;
625+ getSubDataObjectsType ( type ) . forEach ( ( dataObject ) => {
626+ const name = dataObject . getAttribute ( "name" ) ! ;
627+
628+ children [ name ] = nsdDataObject ( dataObject ) ;
629+ } ) ;
630+
631+ getDataAttributesType ( type ) . forEach ( ( dataAttribute ) => {
632+ const name = dataAttribute . getAttribute ( "name" ) ! ;
584633
585- lnClassJson [ name ] = nsdDataObject ( dataObject ) ;
586- } ) ;
634+ children [ name ] = nsdDataAttribute (
635+ dataAttribute ,
636+ undefined ,
637+ undefined ,
638+ ) ;
639+ } ) ;
640+
641+ getServiceDataAttributesType ( type ) . forEach ( ( serviceDataAttribute ) => {
642+ const name = serviceDataAttribute . getAttribute ( "name" ) ! ;
643+
644+ children [ name ] = nsdServiceDataAttribute ( serviceDataAttribute ) ;
645+ } ) ;
646+
647+ return children ;
648+ }
649+
650+ if ( lnClassOrCdc === undefined ) return ;
651+ else if ( isSupportedCdc ( lnClassOrCdc ) )
652+ return CdcChildren ( lnClassOrCdc ) ;
653+ else {
654+ const nsdLnClass74 = doc74 . querySelector ( `LNClass[name="${ lnClassOrCdc } "]` ) ;
655+ const nsdLnClass7420 = doc7420 . querySelector ( `LNClass[name="${ lnClassOrCdc } "]` ) ;
656+
657+ const nsdLnClass = nsdLnClass74 || nsdLnClass7420 ;
658+ if ( ! nsdLnClass ) return undefined ;
659+
660+ const lnClassJson : LNodeDescription = { } ;
661+ getDataObjects ( nsdLnClass ) . forEach ( ( dataObject ) => {
662+ const name = dataObject . getAttribute ( "name" ) ! ;
663+
664+ lnClassJson [ name ] = nsdDataObject ( dataObject ) ;
665+ } ) ;
587666
588- return lnClassJson ;
667+ return lnClassJson
668+ }
589669}
0 commit comments