@@ -32,7 +32,8 @@ interface FmuScalarVariable {
3232 causality : "input" | "output" | "local" | "parameter" | "calculatedParameter" | "independent" ;
3333 variability : "continuous" | "discrete" | "fixed" | "tunable" | "constant" ;
3434 description : string ;
35- start ?: number ;
35+ type : "Real" | "Integer" | "Boolean" | "String" | "Enumeration" ;
36+ start ?: number | boolean | string ;
3637}
3738
3839// ── XML parsing ──
@@ -73,7 +74,14 @@ function parseFmuModelDescription(xml: string): {
7374 "continuous" ) as FmuScalarVariable [ "variability" ] ;
7475 const varDesc = headerAttrs . match ( / \b d e s c r i p t i o n \s * = \s * " ( [ ^ " ] * ) " / ) ?. [ 1 ] ?? "" ;
7576
76- // Extract start value from nested <Real>, <Integer>, etc.
77+ // Extract type based on inner tags
78+ let type : FmuScalarVariable [ "type" ] = "Real" ;
79+ if ( attrs . includes ( "<Integer" ) ) type = "Integer" ;
80+ else if ( attrs . includes ( "<Boolean" ) ) type = "Boolean" ;
81+ else if ( attrs . includes ( "<String" ) ) type = "String" ;
82+ else if ( attrs . includes ( "<Enumeration" ) ) type = "Enumeration" ;
83+
84+ // Extract start value from nested tags
7785 const startMatch = attrs . match ( / \b s t a r t \s * = \s * " ( [ ^ " ] * ) " / ) ;
7886 const start = startMatch ? parseFloat ( startMatch [ 1 ] ?? "" ) : undefined ;
7987
@@ -82,6 +90,7 @@ function parseFmuModelDescription(xml: string): {
8290 causality,
8391 variability,
8492 description : varDesc ,
93+ type,
8594 ...( Number . isFinite ( start ) ? { start : start as number } : { } ) ,
8695 } ) ;
8796 }
@@ -159,23 +168,24 @@ function extractFromZip(zipData: Uint8Array, targetName: string): Uint8Array | n
159168function createSyntheticConnector (
160169 parent : ModelicaClassInstance ,
161170 isInput : boolean ,
162- realType : ModelicaClassInstance | null ,
171+ baseType : ModelicaClassInstance | null ,
172+ typeName = "Real" ,
163173) : ModelicaClassInstance {
164174 // If we have the predefined Real type, clone it and set classKind to CONNECTOR.
165175 // This makes the synthetic connector structurally identical to MSL's
166176 // `connector RealInput = input Real`, ensuring proper plug-compatibility.
167- if ( realType ) {
168- const connector = realType . clone ( ) ;
177+ if ( baseType ) {
178+ const connector = baseType . clone ( ) ;
169179 connector . classKind = ModelicaClassKind . CONNECTOR ;
170180 // Keep the original Real name — isTypeCompatibleWith matches predefined types by name.
171181 // classKind=CONNECTOR is what makes diagram renderers recognize this as a port.
172182 connector . declaredElements = [ ] ;
173183 return connector ;
174184 }
175- // Fallback when Real is not available (no MSL loaded)
185+ // Fallback when base type is not available (no MSL loaded)
176186 const connector = new ModelicaClassInstance ( parent ) ;
177187 connector . classKind = ModelicaClassKind . CONNECTOR ;
178- connector . name = isInput ? "RealInput" : "RealOutput" ;
188+ connector . name = isInput ? ` ${ typeName } Input` : ` ${ typeName } Output` ;
179189 connector . instantiated = true ;
180190 connector . declaredElements = [ ] ;
181191
@@ -436,8 +446,13 @@ export class ModelicaFmuEntity extends ModelicaClassInstance {
436446 this . declaredElements = [ ] ;
437447 this . #syntheticComponents = [ ] ;
438448
439- // Resolve the predefined Real type for non-port component class instances
440- const realType = this . root ?. resolveSimpleName ( "Real" ) as ModelicaClassInstance | null ;
449+ // Resolve the predefined types for non-port and port component class instances
450+ const types = {
451+ Real : this . root ?. resolveSimpleName ( "Real" ) as ModelicaClassInstance | null ,
452+ Integer : this . root ?. resolveSimpleName ( "Integer" ) as ModelicaClassInstance | null ,
453+ Boolean : this . root ?. resolveSimpleName ( "Boolean" ) as ModelicaClassInstance | null ,
454+ String : this . root ?. resolveSimpleName ( "String" ) as ModelicaClassInstance | null ,
455+ } ;
441456
442457 // Segregate by causality to calculate port spacing
443458 const inputs = this . fmuVariables . filter ( ( v ) => v . causality === "input" ) ;
@@ -462,10 +477,14 @@ export class ModelicaFmuEntity extends ModelicaClassInstance {
462477 comp . causality = ModelicaCausality . OUTPUT ;
463478 }
464479
480+ // Find the right base type for this FMU variable
481+ const typeName = v . type === "Enumeration" ? "Integer" : v . type ;
482+ const baseType = types [ typeName as keyof typeof types ] ;
483+
465484 if ( isInput || isOutput ) {
466485 // Create a synthetic CONNECTOR class instance so diagram renderers
467486 // recognise this component as a port (they filter for classKind === CONNECTOR).
468- comp . classInstance = createSyntheticConnector ( this , isInput , realType ) ;
487+ comp . classInstance = createSyntheticConnector ( this , isInput , baseType , typeName ) ;
469488
470489 let y = 0 ;
471490 if ( isInput ) {
@@ -508,9 +527,9 @@ export class ModelicaFmuEntity extends ModelicaClassInstance {
508527 return ModelicaComponentInstance . prototype . annotation . call ( this , name , annotations ) as T | null ;
509528 } ;
510529 } else {
511- // Non-port variables: use Real type
512- if ( realType ) {
513- comp . classInstance = realType . clone ( ) ;
530+ // Non-port variables: use base type
531+ if ( baseType ) {
532+ comp . classInstance = baseType . clone ( ) ;
514533 }
515534 }
516535
0 commit comments