Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

port and interface

This notebook introduces port def and interface, a connection whose ends are all ports; after running it you can declare a real, port-typed connection between two logical components and see it rendered as a diagram.

HeatingSystem (Ch5 nb02) and ControlSystem (Ch1) are logical components with no connection point yet. ApplyHeat::duration (Ch4) is declared but not bound to anything: this notebook gives the two components a typed connection point for a duration signal, showing where it would flow once something produces it, without binding ApplyHeat::duration itself. A port gives each component that connection point, and an interface between two ports states which two connection points are joined.

port def DurationPort {
    out duration : ISQ::DurationValue[0..*];
}

DurationPort carries a value of the same type ApplyHeat already declares for its duration input, not that value itself: the port gives that kind of signal a place to enter the component, not yet a source.

abstract part def HeatingSystem {
    perform action applyHeat : ApplyHeat;
    port durationIn : ~DurationPort;
}

~DurationPort is the conjugate of DurationPort: durationIn receives what a DurationPort sends, the SysML v2 idiom for matching a port to its interface partner.

part def ControlSystem {
    port durationOut : DurationPort;
}

ControlSystem gets the matching, unconjugated port: durationIn and durationOut declare the same underlying port type, which is what makes them a type-compatible pair.

part def Toaster :> ToastingSystem {
    attribute cycleTime : ISQ::DurationValue;
    part heating : HeatingSystem;
    part control : ControlSystem;
    interface durationInterface connect control.durationOut to heating.durationIn;
    allocation heatAllocation allocate toastBread.applyHeat to heating;
}

The interface connects the two ports by their owning parts’ names, control and heating, both already composed inside Toaster. Naming it (durationInterface) makes it visible to model.query(), the same convention nb02’s allocation already follows. Toaster’s body carries nb02’s heatAllocation forward here too, alongside the new interface: restating a member from the previous notebook, the way this chapter’s convention already restates cycleTime, heating and control in every notebook that touches Toaster.

An interface’s ends must resolve to real features. The negative control below connects to a part that was never composed.

Neg control diagnostics: 'unresolved reference: undefined_receiver'

The diagnostic reports an unresolved reference: undefined_receiver was never composed inside B.

Port type mismatches: []

An empty list means durationIn and durationOut declare related types (equal, or one specializing the other): the check compares declared port types, not whether the conjugation itself is the correct one for this interface.

@startuml
skinparam linetype ortho
rectangle "Toaster" as n1 <<part def>> {
  rectangle "heating : HeatingSystem" as n2 <<part>> {
    port "durationIn\n: ~DurationPort" as n3
  }
  rectangle "control : ControlSystem" as n4 <<part>> {
    port "durationOut\n: DurationPort" as n5
  }
}
n5 -- n3 : «interface» durationInterface
@enduml

Loading...

The diagram shows control and heating, the two parts of Toaster, each drawn with its own named port -- durationOut on control, durationIn on heating -- connected by the durationInterface port connection. It supports the conclusion that ControlSystem and HeatingSystem are now joined through a single, type-checked connection point between those two specific ports, not a claim about what flows through ApplyHeat itself.

The assembled definitions loaded without error, and the diagram rendered directly from the loaded model shows the same control-to-heating connection, now by its own durationOut-to-durationIn port names rather than the interface label alone.

Try the chapter exercise in exercises/ch05/exercise.ipynb: add a CoffeeFlow assembly with a pump and a filterUnit, each with a matching port joined by a named interface, confirm port_type_mismatches() returns an empty list, and render the interconnection diagram.