@@ -20,14 +20,13 @@ const SOPC_TO_UA_TYPE_MAP: Record<string, string> = {
2020} ;
2121
2222// Attribute mappings for each object type pair
23- const UA_TO_SOPC_ATTR_MAP : Record < string , Record < string , string > > = {
23+ const UA_TO_SOPC_ATTR_MAP : Record < string , Record < string , string | string [ ] > > = {
2424 UAProcToSopcProc : {
2525 yPulse : "PulsTag" ,
2626 xSchedule : "ScheduleTag" ,
2727 } ,
2828 UAApplToSopcProc : {
2929 xAllowActive : "AllowActiveTag" ,
30- xDesiredMode : "DesModeTag" ,
3130 yStatus : "StatusTag" ,
3231 } ,
3332 UACvr : {
@@ -47,7 +46,6 @@ const UA_TO_SOPC_ATTR_MAP: Record<string, Record<string, string>> = {
4746 xNotValid : "NotValidTag" ,
4847 xProcessValue : "PVTag" ,
4948 yCalcSetpoint : "SpCalcTag" ,
50- xDesiredActive : "MvSwitchTag" ,
5149 yActive : "MvActiveTag" ,
5250 xAuto : "AutoTag" ,
5351 xExtern : "CompTag" ,
@@ -80,14 +78,13 @@ const UA_TO_SOPC_ATTR_MAP: Record<string, Record<string, string>> = {
8078 } ,
8179} ;
8280
83- const SOPC_TO_UA_ATTR_MAP : Record < string , Record < string , string > > = {
81+ const SOPC_TO_UA_ATTR_MAP : Record < string , Record < string , string | string [ ] > > = {
8482 SopcProcToUAProc : {
8583 PulsTag : "yPulse" ,
8684 ScheduleTag : "xSchedule" ,
8785 } ,
8886 SopcProcToUAAppl : {
89- AllowActiveTag : "xAllowActive" ,
90- DesModeTag : "xDesiredMode" ,
87+ AllowActiveTag : [ "xAllowActive" , "xDesiredMode" ] ,
9188 StatusTag : "yStatus" ,
9289 } ,
9390
@@ -119,11 +116,10 @@ const SOPC_TO_UA_ATTR_MAP: Record<string, Record<string, string>> = {
119116 AutoTag : "xAuto" ,
120117 WhiTag : "xWindupHigh" ,
121118 WloTag : "xWindupLow" ,
122- CompTag : "xExtern" ,
119+ CompTag : [ "xExtern" , "xDesiredActive" ] ,
123120 ToCompTag : "yToComp" ,
124121 ToLocalTag : "yToLocal" ,
125122 MvActiveTag : "yActive" ,
126- MvSwitchTag : "xDesiredActive" ,
127123 } ,
128124 SopcEvr : {
129125 MeasTag : "yMeas" ,
@@ -154,14 +150,19 @@ export function sopcToUA(obj: SepticObject): SepticObject {
154150 const uaAttrName = attrMap [ attr . key ] ;
155151 if ( uaAttrName ) {
156152 const value = getUAValue ( attr ) ;
157- uaObj
158- . getAttribute ( uaAttrName )
159- ?. setValues (
160- createAttrValues (
161- [ value . length ? `"s=${ value } "` : `""` ] ,
162- SepticTokenType . string ,
163- ) ,
164- ) ;
153+ const uaAttrNames = Array . isArray ( uaAttrName )
154+ ? uaAttrName
155+ : [ uaAttrName ] ;
156+ for ( const name of uaAttrNames ) {
157+ uaObj
158+ . getAttribute ( name )
159+ ?. setValues (
160+ createAttrValues (
161+ [ value . length ? `"s=${ value } "` : `""` ] ,
162+ SepticTokenType . string ,
163+ ) ,
164+ ) ;
165+ }
165166 }
166167 }
167168 return uaObj ;
@@ -177,6 +178,10 @@ function getUAValue(attr: SepticAttribute): string {
177178 }
178179 return value ;
179180}
181+
182+ function getSopcValue ( attr : SepticAttribute ) : string {
183+ return attr . getFirstValue ( ) ?. replace ( "s=" , "" ) || "" ;
184+ }
180185/**
181186 * Converts a UA object to a Sopc object
182187 * @param obj The UA object to convert
@@ -198,24 +203,56 @@ export function uaToSopc(obj: SepticObject): SepticObject {
198203 for ( const attr of obj . attributes ) {
199204 const sopcAttrName = attrMap [ attr . key ] ;
200205 if ( sopcAttrName ) {
201- sopcObj
202- . getAttribute ( sopcAttrName )
203- ?. setValues (
204- createAttrValues (
205- [ attr . values [ 0 ] ?. value . replace ( "s=" , "" ) || "" ] ,
206- SepticTokenType . string ,
207- ) ,
208- ) ;
206+ const sopcAttrNames = Array . isArray ( sopcAttrName )
207+ ? sopcAttrName
208+ : [ sopcAttrName ] ;
209+ for ( const name of sopcAttrNames ) {
210+ const value = getSopcValue ( attr ) ;
211+ if ( value === "" ) {
212+ continue ;
213+ }
214+ sopcObj
215+ . getAttribute ( name )
216+ ?. setValues (
217+ createAttrValues (
218+ [ `"${ value } "` ] ,
219+ SepticTokenType . string ,
220+ ) ,
221+ ) ;
222+ }
209223 }
210224 }
211225 return sopcObj ;
212226}
213227
214- function sopcToUAProcAndAppl ( sopcProc : SepticObject ) : SepticObject [ ] {
228+ function sopcToUAProcAndAppl (
229+ sopcProc : SepticObject ,
230+ simulator : boolean = false ,
231+ ) : SepticObject [ ] {
215232 const generator = new SepticObjectGenerator ( ) ;
233+ const attributes = [
234+ {
235+ key : "DefaultNameSpaceURI" ,
236+ type : SepticTokenType . string ,
237+ values : [ '"urn:equinor:MiniOpcUaServer"' ] ,
238+ } ,
239+ {
240+ key : "SecurityMode" ,
241+ type : SepticTokenType . identifier ,
242+ values : [ "UA_MESSAGESECURITYMODE_NONE" ] ,
243+ } ,
244+ ] ;
245+ if ( simulator ) {
246+ attributes . push ( {
247+ key : "RunMenu" ,
248+ type : SepticTokenType . identifier ,
249+ values : [ "ON" ] ,
250+ } ) ;
251+ }
216252 const uaProc = generator . createObject (
217253 "UAProc" ,
218254 sopcProc . identifier ?. name || "" ,
255+ attributes ,
219256 ) ;
220257 const uaAppl = generator . createObject (
221258 "UAAppl" ,
@@ -228,38 +265,52 @@ function sopcToUAProcAndAppl(sopcProc: SepticObject): SepticObject[] {
228265 const uaProcAttr = attrsMapUAProc [ attr . key ] ;
229266 const value = getUAValue ( attr ) ;
230267 if ( uaProcAttr ) {
231- uaProc
232- . getAttribute ( uaProcAttr )
233- ?. setValues (
234- createAttrValues (
235- [ value . length ? `"s=${ value } "` : `""` ] ,
236- SepticTokenType . string ,
237- ) ,
238- ) ;
268+ const uaProcAttrNames = Array . isArray ( uaProcAttr )
269+ ? uaProcAttr
270+ : [ uaProcAttr ] ;
271+ for ( const name of uaProcAttrNames ) {
272+ uaProc
273+ . getAttribute ( name )
274+ ?. setValues (
275+ createAttrValues (
276+ [ value . length ? `"s=${ value } "` : `""` ] ,
277+ SepticTokenType . string ,
278+ ) ,
279+ ) ;
280+ }
239281 }
240282 const uaApplAttr = attrsMapUAAppl [ attr . key ] ;
241283 if ( uaApplAttr ) {
242- uaAppl
243- . getAttribute ( uaApplAttr )
244- ?. setValues (
245- createAttrValues (
246- [ value . length ? `"s=${ value } "` : `""` ] ,
247- SepticTokenType . string ,
248- ) ,
249- ) ;
284+ const uaApplAttrNames = Array . isArray ( uaApplAttr )
285+ ? uaApplAttr
286+ : [ uaApplAttr ] ;
287+ for ( const name of uaApplAttrNames ) {
288+ uaAppl
289+ . getAttribute ( name )
290+ ?. setValues (
291+ createAttrValues (
292+ [ value . length ? `"s=${ value } "` : `""` ] ,
293+ SepticTokenType . string ,
294+ ) ,
295+ ) ;
296+ }
250297 }
251298 }
299+ if ( simulator ) {
300+ return [ uaProc ] ;
301+ }
252302 return [ uaProc , uaAppl ] ;
253303}
254304
255305function uaProcAndApplToSopc (
256306 uaProc : SepticObject ,
257- uaAppl : SepticObject ,
307+ uaAppl : SepticObject | undefined ,
308+ simulator : boolean = false ,
258309) : SepticObject | undefined {
259310 const generator = new SepticObjectGenerator ( ) ;
260311 const sopcProc = generator . createObject (
261312 "SopcProc" ,
262- uaAppl . identifier ?. name || "" ,
313+ uaAppl ?. identifier ?. name || uaProc . identifier ?. name || "" ,
263314 [
264315 {
265316 key : "ServName" ,
@@ -268,8 +319,8 @@ function uaProcAndApplToSopc(
268319 } ,
269320 {
270321 key : "Site" ,
271- type : SepticTokenType . string ,
272- values : [ "AIM_AIMGUI" ] ,
322+ type : SepticTokenType . identifier ,
323+ values : [ simulator ? "OPCSIMUL" : "AIM_AIMGUI" ] ,
273324 } ,
274325 ] ,
275326 ) ;
@@ -279,27 +330,44 @@ function uaProcAndApplToSopc(
279330 for ( const attr of uaProc . attributes ) {
280331 const sopcAttr = attrsMapUAProc [ attr . key ] ;
281332 if ( sopcAttr ) {
282- sopcProc
283- . getAttribute ( sopcAttr )
284- ?. setValues (
285- createAttrValues (
286- [ attr . values [ 0 ] ?. value . replace ( "s=" , "" ) || "" ] ,
287- SepticTokenType . string ,
288- ) ,
289- ) ;
333+ const sopcAttrNames = Array . isArray ( sopcAttr )
334+ ? sopcAttr
335+ : [ sopcAttr ] ;
336+ for ( const name of sopcAttrNames ) {
337+ const value = getSopcValue ( attr ) ;
338+ if ( value === "" ) {
339+ continue ;
340+ }
341+ sopcProc
342+ . getAttribute ( name )
343+ ?. setValues (
344+ createAttrValues (
345+ [ `"${ value } "` ] ,
346+ SepticTokenType . string ,
347+ ) ,
348+ ) ;
349+ }
290350 }
291351 }
352+ if ( ! uaAppl ) {
353+ return sopcProc ;
354+ }
292355 for ( const attr of uaAppl . attributes ) {
293356 const sopcAttr = attrsMapUAAppl [ attr . key ] ;
294357 if ( sopcAttr ) {
295- sopcProc
296- . getAttribute ( sopcAttr )
297- ?. setValues (
298- createAttrValues (
299- [ attr . values [ 0 ] ?. value . replace ( "s=" , "" ) || "" ] ,
300- SepticTokenType . string ,
301- ) ,
302- ) ;
358+ const sopcAttrNames = Array . isArray ( sopcAttr )
359+ ? sopcAttr
360+ : [ sopcAttr ] ;
361+ for ( const name of sopcAttrNames ) {
362+ sopcProc
363+ . getAttribute ( name )
364+ ?. setValues (
365+ createAttrValues (
366+ [ attr . values [ 0 ] ?. value . replace ( "s=" , "" ) || "" ] ,
367+ SepticTokenType . string ,
368+ ) ,
369+ ) ;
370+ }
303371 }
304372 }
305373 return sopcProc ;
@@ -308,22 +376,28 @@ function uaProcAndApplToSopc(
308376export function convertOPCObjects (
309377 cnfg : SepticCnfg ,
310378 direction : "sopc-to-ua" | "ua-to-sopc" ,
379+ simulator : boolean = false ,
311380) : SepticCnfg {
312381 const typeMap =
313382 direction === "sopc-to-ua" ? SOPC_TO_UA_TYPE_MAP : UA_TO_SOPC_TYPE_MAP ;
314383 const convertFn = direction === "sopc-to-ua" ? sopcToUA : uaToSopc ;
315384 for ( let i = 0 ; i < cnfg . objects . length ; i ++ ) {
316385 const obj = cnfg . objects [ i ] ! ;
317386 if ( obj . type == "SopcProc" && direction === "sopc-to-ua" ) {
318- const uaObjects = sopcToUAProcAndAppl ( obj ) ;
387+ const uaObjects = sopcToUAProcAndAppl ( obj , simulator ) ;
319388 cnfg . objects . splice ( i , 1 , ...uaObjects ) ;
320389 i += uaObjects . length - 1 ;
321390 continue ;
322391 }
323392 if ( obj . type == "UAProc" && direction === "ua-to-sopc" ) {
324- const sopcProc = uaProcAndApplToSopc ( obj , cnfg . objects [ i + 1 ] ! ) ;
393+ const uaAppls = cnfg . getObjectsByType ( "UAAppl" ) ;
394+ const sopcProc = uaProcAndApplToSopc (
395+ obj ,
396+ uaAppls . length ? uaAppls [ 0 ] : undefined ,
397+ simulator ,
398+ ) ;
325399 if ( sopcProc ) {
326- cnfg . objects . splice ( i , 2 , sopcProc ) ;
400+ cnfg . objects . splice ( i , uaAppls . length ? 2 : 1 , sopcProc ) ;
327401 }
328402 }
329403 if ( typeMap [ obj . type ] ) {
0 commit comments