Attribute
Port uses C# attributes to declaratively define package registration, API generation, dependency injection, and workflow control. This page is a categorized reference for all Port attributes.
Quick Reference
Summary table of all Port attributes.
| Category | Attribute | Target | Description |
|---|---|---|---|
| Portdic | [Portdic] | class | Register main window as Port project entry point |
| Package | [Package] | class | Register Port-managed package |
[Handler] | property | Inject IPackageHandler (log + property) | |
[Preset] | method | Initialization after injection | |
[API] | property, field | Generate REST API endpoint | |
[Valid] | method | Validation gate | |
[Comment] | property | API documentation | |
| Controller | [Controller] | class | Flow controller |
[Flow] | class | Workflow definition | |
[FlowStep] | method | Workflow step | |
[Handler] | property | Inject IFlowHandler (basic step control) | |
[Handler] | property | Inject IFlowWithModelHandler<T> (lifecycle events with model) | |
[Handler] | property | Inject ISchedulerHandler<T> (transfer scheduling) | |
[Model] | class | Define flow model class | |
[ModelBinding] | property | Bind model property to a Port entry | |
[TMC] | property | Inject ITransferModule<T> into a [Flow] class | |
[LMC] | property | Inject ILoadModule (load port) into a [Flow] class | |
[PMC] | property | Inject IProcessModule (process chamber) into a [Flow] class | |
[TransferScore] | method | Define pick/place priority score for the transfer scheduler | |
[FlowWatcherCompare] | method | Step condition watcher | |
[FlowWatcherAction] | method | Step completion action | |
[Timeout] | method | Step timeout | |
| Document | [Document] | class | Source document path |
[Save] | method | Output file paths | |
[ColumnHeader] | property | Column header mapping | |
[EntryKey] | property | Key column | |
[EntryProperty] | property | Property column | |
[EntryDataType] | property | Data type |
Portdic
[Portdic("repoName")] is the entry-point attribute. It must be applied to the application's main class (e.g., MainWindow) and registers the project under the given repository name. All Port services, packages, controllers, and flows are resolved within this project scope.
The repoName string must match the name used in .page file paths and Port.Push() / Port.Add() calls throughout the project.
Constructor:
Portdic(string reponame, string pull_path = "")
| Parameter | Type | Required | Description |
|---|---|---|---|
reponame | string | Yes | Repository name — must match all Port.Add() / Port.Push() calls in the project |
pull_path | string | No | Local directory path for pulling remote data; defaults to "" (disabled) |
[Portdic("EQ-01-B05")]
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Port.App<MainWindow>();
Port.Add<SessionHelper>("Session");
Port.Add<LoadportController>("LP1");
Port.Add<LoadportController>("LP2");
Port.Add<WTRController>("WTR");
}
}
Package Attributes
Attributes used for defining package classes and generating APIs.
| Attribute | Target | Injected Type | Arguments | Description |
|---|---|---|---|---|
[Package] | class | — | — | Registers class as a Port-managed package |
[Handler] | property | IPackageHandler | — | Injects handler — unified access to logging and entry property |
[Preset] | method | — | — | Called once after injection; use for initialization and event wiring |
[API] | property, field | — | EntryDataType, PropertyFormat, keys | Generates REST API endpoint |
[Valid] | method | — | message | Validation gate; returns error message when invalid |
[Comment] | property | — | string | API property documentation |
Package
Registers a class as a managed package in the Port Dictionary system.
Constructor: No parameters.
Package()
[Package]
public class Bulb
{
[Handler]
public IPackageHandler Handler { get; set; }
[API(EntryDataType.Enum)]
public string OffOn { get; set; } = "Off";
}
Handler
Injects IPackageHandler, which provides unified access to logging and entry property values. Use SetLogger in [Preset] to enable file logging, then call Write anywhere inside the package.
Constructor: No parameters — applies to both [Handler] and [Preset].
Handler()
Preset()
[Package]
public class Heater
{
[Handler]
public IPackageHandler Handler { get; set; }
[Preset]
public void Preset()
{
// Enable file logging — writes to C:\Logs\Heater\
Handler.SetLogger(@"C:\Logs");
}
[API]
public double Temp
{
get
{
// Read entry property (set in .page via property:{...})
if (Handler.EntryProperty.TryToGetValue("Unit", out string unit))
{
Handler.Write($"[INFO] Unit={unit}");
return unit == "F" ? 212.0 : 100.0;
}
return double.NaN;
}
}
}
IPackageHandler members:
| Member | Description |
|---|---|
SetLogger(rootPath) | Enable file logging; creates rootPath/packageName/ sub-directory |
SetLogger(rootPath, conf) | Same with rotation and retention options via PortLogConfiguration |
Write(message) | Write a plain text log entry |
Write(code, header, dict) | Write a structured log entry with LogTypeCode, header, and key-value data |
EntryProperty | Current IProperty for the active Get/Set request; use TryToGetValue to read values |
IProperty.TryToGetValue usage:
// .page entry definition
// RoomTemp f8 property:{"Unit":"C","Max":"300"}
// Inside a package API property getter:
if (Handler.EntryProperty.TryToGetValue("Unit", out string unit))
{
// unit == "C"
}
if (Handler.EntryProperty.TryToGetValue("Max", out string max))
{
double limit = double.Parse(max); // limit == 300.0
}
API
Automatically registers a property as a REST API endpoint. Specify the data type with EntryDataType.
Constructors:
API()
API(EntryDataType dataType)
API(string key)
API(EntryDataType dataType, PropertyFormat format)
API(EntryDataType dataType, PropertyFormat format, params string[] required)
API(EntryDataType dataType, PropertyFormat format, params int[] required)
| Parameter | Type | Description |
|---|---|---|
dataType | EntryDataType | SECS-compatible data type of the exposed property (default: Text) |
key | string | Custom entry key name; use when the property name differs from the entry key |
format | PropertyFormat | Serialization format for multi-value properties (Json, Array, etc.) |
required | string[] or int[] | Required property keys (strings) or required index list (ints) for structured types |
// Basic usage
[API]
public string Status { get; set; }
// Enum type
[API(EntryDataType.Enum)]
public string OffOn { get; set; }
// Numeric with JSON property keys
[API(EntryDataType.Num, PropertyFormat.Json, "Unit")]
public double Temp1 { get; set; }
// String type
[API(EntryDataType.Char)]
public string Power { get; set; }
// List type
[API(EntryDataType.List, PropertyFormat.Array, 0, 1, 2)]
public List<string> Readings { get; set; }
EntryDataType values:
| Type | Description |
|---|---|
EntryDataType.Text | Text |
EntryDataType.Num | Numeric (double) |
EntryDataType.Char | ASCII string |
EntryDataType.Enum | Enumeration |
EntryDataType.List | List |
Linking an API property to a Package in .page:
Use pkg:PackageName.PropertyName in the .page file to connect an entry to a [API] property in a [Package] class.
# device/io.page
RoomTemp f8 pkg:Heater.Temp
BulbStatus enum pkg:Bulb.OffOn
Power char pkg:Bulb.Power
// Package class — property names must match the pkg: declaration
[Package]
public class Heater
{
[API]
public double Temp { get; set; } // → pkg:Heater.Temp
}
[Package]
public class Bulb
{
[API(EntryDataType.Enum)]
public string OffOn { get; set; } // → pkg:Bulb.OffOn
[API(EntryDataType.Char)]
public string Power { get; set; } // → pkg:Bulb.Power
}
Valid
Defines a validation method for the package. When it returns false, the error message passed as argument is displayed.
Constructor:
Valid(string invalidComment)
| Parameter | Type | Description |
|---|---|---|
invalidComment | string | Error message returned to the caller when the method returns false |
[Valid("Device not connected")]
public bool Valid()
{
return serialPort.IsOpen;
}
Comment
Adds a description to an API property.
Constructors:
Comment(string comment)
Comment(Dictionary<string, string> comment)
| Parameter | Type | Description |
|---|---|---|
comment | string | Single description string for the property |
comment | Dictionary<string, string> | Multi-language or multi-key description map |
[API, Comment("Current temperature (Celsius)")]
public double Temperature { get; set; }
Controller Attributes
Attributes used for defining and controlling workflows (process flows).
| Attribute | Target | Injected Type | Arguments | Description |
|---|---|---|---|---|
[Controller] | class | — | — | Defines a controller containing flows |
[Flow] | class | — | key | Defines a workflow class (inner class of Controller) |
[FlowStep] | method | — | index, relatedEntry | Defines a workflow step |
[Handler] | property | IFlowHandler | — | Injects basic flow step control into a Flow class |
[Handler] | property | IFlowWithModelHandler<T> | — | Injects model-bound handler with lifecycle events |
[Handler] | property | ISchedulerHandler<T> | — | Injects transfer scheduler handler |
[Model] | class | — | — | Defines a flow model class; properties use [ModelBinding] |
[ModelBinding] | property | Entry | controllerName, entryKey | Binds a model property to a Port entry |
[TMC] | property | ITransferModule<T> | — | Injects transfer module controller; T is the arm action type |
[LMC] | property | ILoadModule | capacity | Injects load port module; capacity = number of slots |
[PMC] | property | IProcessModule | capacity | Injects process chamber module; capacity = number of slots |
[TransferScore] | method | — | location, direction | Returns int score for scheduler pick/place decisions |
[FlowWatcherCompare] | method | — | entry, op, value | Defines step execution condition |
[FlowWatcherAction] | method | — | entry, value | Defines action on step completion |
[Timeout] | method | — | ms, controller, alarmid | Sets step timeout and alarm |
Controller
[Controller] defines a controller that contains multiple flows. All [Flow] classes must be declared as inner classes inside a [Controller] class.
Constructors:
Controller()
Flow(string key)
| Attribute | Parameter | Type | Description |
|---|---|---|---|
[Controller] | — | — | No parameters; marks the class as a Port flow controller |
[Flow] | key | string | Flow name — used to identify and trigger the flow at runtime |
// Model class — defined outside the controller
[Model]
public class LoadportModel
{
[ModelBinding(Controller.LP1, EFEM.LP1_Command)]
[ModelBinding(Controller.LP2, EFEM.LP2_Command)]
public Entry LP_Command { get; set; }
[ModelBinding(Controller.LP1, EFEM.LP1_Main_Air_i)]
[ModelBinding(Controller.LP2, EFEM.LP2_Main_Air_i)]
public Entry LP_Main_Air_i { get; set; }
}
// Controller — [Flow] classes must be inner classes
[Controller]
public class LoadportController
{
[Flow("Load")]
public class FoupLoadFlow
{
[Handler]
public IFlowHandler Handler { get; set; } = null!;
[FlowStep(0)]
public void StatusCheck(LoadportModel m)
{
Handler.ClearAlarm(-1);
Debug.WriteLine(m.LP_Main_Air_i.Name + " : " + m.LP_Main_Air_i.Value.String());
Handler.Next();
}
[FlowStep(1)]
public void SendLoadCommand(LoadportModel m)
{
Handler.Next();
}
[FlowStep(2)]
public void Done(LoadportModel m)
{
Handler.Done();
}
}
}
Handler
Injects a handler interface into a [Flow] class. The injected type is determined by the property's declared type.
| Property type | Purpose |
|---|---|
IFlowHandler | Basic step control (Next(), Done(), logging) |
IFlowWithModelHandler<T> | Lifecycle events that carry the bound model |
ISchedulerHandler<T> | Transfer scheduling for robot arm coordination |
FlowStep methods always receive the model as a method parameter — they do not inject it as a property.
Constructor: No parameters — applies to [Handler] and [Preset].
Handler()
Preset()
// [Handler] — basic step control
[Flow("Load")]
public class FoupLoadFlow
{
[Handler]
public IFlowHandler Handler { get; set; } = null!;
[Preset]
public void Preset()
{
Handler.SetLogger(@"D:\logs");
}
[FlowStep(0)]
public void StatusCheck(LoadportModel m)
{
Handler.ClearAlarm(-1);
Handler.Next();
}
[FlowStep(1)]
public void Done(LoadportModel m)
{
Handler.Done();
}
}
// [Handler] — lifecycle events with model
//
// OnFlowFinished fires after handler.Done() completes.
// e.Model carries the bound model so the caller can act on the result
// (e.g. notify a scheduler that this transfer location is free).
[Flow("Place")]
public class Place
{
[Handler]
public IFlowWithModelHandler<WTRCommModel> handler { get; set; } = null!;
[Handler]
public ISchedulerHandler<DualArmActionArgs> scheduler { get; set; } = null!;
[Preset]
public void Preset()
{
handler.SetLogger(@"D:\logs");
handler.OnFlowOccured += Handler_OnFlowOccured;
handler.OnFlowFinished += Handler_OnFlowFinished;
}
// Called when the flow is triggered (before Step 0 runs).
// e.Model is the bound model populated at flow start.
private void Handler_OnFlowOccured(object sender, PortFlowOccuredWithModelArgs<WTRCommModel> e)
{
// e.Model.Target, e.Model.Source, etc. are already populated
}
// Called after handler.Done() returns the flow to Idle.
// Use e.Model to read the final state and notify downstream systems.
private void Handler_OnFlowFinished(object sender, FlowFinishedWithModelArgs<WTRCommModel> e)
{
// e.Model.Target contains the destination that was set when the flow was triggered
scheduler.TransferCompleted(e.Model.Target);
}
[FlowStep(0)]
public void CheckAction(WTRCommModel m)
{
handler.WriteLog("CheckAction", WriteRule.NotAllowDuplicate | WriteRule.WithDebug);
handler.Next();
}
[FlowStep(1)]
public void Done(WTRCommModel m)
{
handler.Done(); // triggers Handler_OnFlowFinished after returning to Idle
}
}
IFlowHandler members:
| Member | Description |
|---|---|
Next() | Move to the next FlowStep |
Done() | Complete the flow and return to Idle synchronously |
Move(stepName) | Jump to a named step |
Alert(message) | Send an alert notification |
OccuredAlarm(alid) | Raise an alarm by alarm ID |
ClearAlarm(alid = -9999) | Clear alarm; -9999 clears all alarms |
SetLogger(rootPath) | Enable file logging under rootPath/flowName/ |
WriteLog(message) | Write a log entry |
WriteLog(message, rule) | Write a log entry with WriteRule flags |
WriteRule flags:
| Flag | Description |
|---|---|
None | Write to file only (default) |
NotAllowDuplicate | Skip consecutive duplicate messages |
WithDebug | Also write to Debug.WriteLine |
WithConsole | Also write to Console.WriteLine |
WithTrace | Also write to Trace.WriteLine |
IFlowWithModelHandler<T> additional members:
| Member | Description |
|---|---|
T Model | The model instance bound to this flow |
OnFlowOccured | Fired when the flow starts |
OnFlowFinished | Fired when the flow completes; e.Model carries the bound model |
FlowStep
Registers a method as a workflow step. Steps are ordered by index number. The bound model is received as a method parameter — omit it if no model is needed.
Constructors:
FlowStep(int index = 0, params string[] relatedEntry)
FlowStep(string prev)
FlowStep(int index, ushort ceid, params string[] relatedEntry)
| Overload | Parameter | Type | Description |
|---|---|---|---|
| Default | index | int | Step execution order; lower numbers run first (default: 0) |
| Default | relatedEntry | string[] | Entry keys that trigger step re-evaluation on value change |
| Named-prev | prev | string | Name of the preceding step; use when step order is defined by name instead of index |
| CEID | index | int | Step execution order |
| CEID | ceid | ushort | Collection Event ID to fire when this step completes |
| CEID | relatedEntry | string[] | Entry keys that trigger step re-evaluation |
// With model parameter
[FlowStep(0)]
public void StatusCheck(LoadportModel m)
{
Debug.WriteLine(m.LP_Main_Air_i.Value.String());
Handler.Next();
}
[FlowStep(1)]
public void SendCommand(LoadportModel m)
{
Handler.Next();
}
[FlowStep(2)]
public void Done(LoadportModel m)
{
Handler.Done(); // Complete flow and return to Idle
}
FlowWatcherCompare
Defines pre/post conditions for a step. All conditions must be met before proceeding to the next step.
Constructors:
FlowWatcherCompare(string a, string op, object b, bool OR = false)
FlowWatcherCompare(string controller_name, string model_key_name, string op, object value, bool OR = false)
| Overload | Parameter | Type | Description |
|---|---|---|---|
| Direct | a | string | Left-hand entry key; prefix @ to reference a model binding |
| Direct | op | string | Comparison operator: >=, <=, >, <, ==, != |
| Direct | b | object | Right-hand value or entry key |
| Direct | OR | bool | true = combine with previous watcher using OR logic (default: false = AND) |
| Controller | controller_name | string | Limit this watcher to the named controller instance (e.g. "LP1") |
| Controller | model_key_name | string | Entry key from the controller's model |
| Controller | op | string | Comparison operator |
| Controller | value | object | Right-hand comparison value |
| Controller | OR | bool | OR logic flag (default: false) |
[FlowStep]
[FlowWatcherCompare("@Temp1", ">=", 50)] // Model binding (@)
[FlowWatcherCompare("room2.HeaterTemp4", ">=", 100)] // Direct reference
[FlowWatcherCompare("room2.HeaterTemp5", ">=", Room2.HeaterTemp4)] // Entry-to-entry comparison
public void Step1()
{
Handler.Next();
}
Supported operators: >=, <=, >, <, ==, !=
FlowWatcherAction
Automatically sets a value when a step completes.
Constructors:
FlowWatcherAction(string target, object v)
FlowWatcherAction(string controller_name, string target, object v)
| Overload | Parameter | Type | Description |
|---|---|---|---|
| Direct | target | string | Entry key to write to when the step finishes |
| Direct | v | object | Value to write |
| Controller | controller_name | string | Limit this action to the named controller instance |
| Controller | target | string | Entry key to write to |
| Controller | v | object | Value to write |
[FlowStep]
[FlowWatcherAction("room2.BulbOnOff", "Off")] // Sets BulbOnOff = "Off" on completion
[FlowWatcherAction(Room2.BulbOnOff, "On")] // Using token constants
public void Step1()
{
Handler.Next();
}
Model
[Model] marks a class as a flow model. Properties are of type Entry and decorated with [ModelBinding] to bind to Port entries. The platform instantiates the model and passes it as a method parameter to each [FlowStep].
Multiple [ModelBinding] attributes on one property let the same model class serve different controllers — the binding that matches the running controller's name is applied.
Constructors:
// [Model]
Model()
Model(string controllerName)
// [ModelBinding]
ModelBinding(string controller_name, string key)
ModelBinding(string key)
| Attribute | Parameter | Type | Description |
|---|---|---|---|
[Model] | — | — | No parameters; marks the class as a Port flow model |
[Model] | controllerName | string | Restrict this model to a specific controller name |
[ModelBinding] | controller_name | string | Controller instance name this binding applies to (e.g. "LP1") |
[ModelBinding] | key | string | Port entry key to bind the property to |
[ModelBinding] (1-arg) | key | string | Bind to this entry for all controllers (no controller filter) |
// Define the model class — outside the controller
[Model]
public class LoadportModel
{
// Bound to LP1_Command when run under "LP1", LP2_Command under "LP2"
[ModelBinding(Controller.LP1, EFEM.LP1_Command)]
[ModelBinding(Controller.LP2, EFEM.LP2_Command)]
public Entry LP_Command { get; set; }
[ModelBinding(Controller.LP1, EFEM.LP1_Configure_Value_i)]
[ModelBinding(Controller.LP2, EFEM.LP2_Configure_Value_i)]
public Entry LP_Configure_Value_i { get; set; }
[ModelBinding(Controller.LP1, EFEM.LP1_Main_Air_i)]
[ModelBinding(Controller.LP2, EFEM.LP2_Main_Air_i)]
public Entry LP_Main_Air_i { get; set; }
}
// Receive model as a parameter in each FlowStep
[FlowStep(0)]
public void StatusCheck(LoadportModel m)
{
Debug.WriteLine(m.LP_Configure_Value_i.Name + " : " + m.LP_Configure_Value_i.Value.String());
Handler.ClearAlarm(-1);
Handler.Next();
}
[FlowStep(1)]
public void SendLoadCommand(LoadportModel m)
{
Debug.WriteLine(m.LP_Main_Air_i.Name + " : " + m.LP_Main_Air_i.Value.String());
Handler.Next();
}
Entry members:
| Member | Description |
|---|---|
Name | Entry key string (e.g. "EFEM.LP1_Command") |
Value.String() | Current value as string |
Value.Double() | Current value as double |
Value.Int() | Current value as int |
Timeout
Sets a timeout for a FlowStep. When the step exceeds the duration, the specified alarm is raised on the given controller.
Constructor:
Timeout(int ms, string controller, int alarmid)
| Parameter | Type | Description |
|---|---|---|
ms | int | Timeout duration in milliseconds |
controller | string | Controller instance name this timeout applies to (e.g. "LP1") |
alarmid | int | Alarm ID to raise when the timeout expires |
[FlowStep]
[Timeout(0, 0)] // min, max (0 = unlimited)
public void Step1()
{
Handler.Next();
}
TMC / LMC / PMC
[TMC], [LMC], and [PMC] inject module interfaces into a [Flow] class. They declare which equipment modules the flow can interact with and provide the scheduler with the equipment topology needed to plan transfers.
| Attribute | Injected Type | Argument | Description |
|---|---|---|---|
[TMC] | ITransferModule<T> | — | Transfer robot arm; T is the arm action type (e.g. DualArmAction) |
[LMC(n)] | ILoadModule | capacity (int) | Load port; capacity = number of wafer slots (e.g. 25 for a FOUP) |
[PMC(n)] | IProcessModule | capacity (int) | Process chamber; capacity = number of substrate slots |
Constructors:
TMC()
LMC(int capacity)
PMC(int capacity)
[Flow("Queued")]
public class Queued
{
[TMC] public ITransferModule<DualArmAction> TM1 { set; get; } = null!;
[LMC(25)] public ILoadModule LP1 { get; set; } = null!;
[LMC(25)] public ILoadModule LP2 { get; set; } = null!;
[PMC(1)] public IProcessModule Stage1 { set; get; } = null!;
[PMC(1)] public IProcessModule Stage2 { set; get; } = null!;
[PMC(1)] public IProcessModule Aligner { set; get; } = null!;
[Preset]
public void Preset()
{
TM1.SetRule(TransferRule.PreferSwap);
TM1.SetChildLocation("Upper", "Lower");
TM1.OnRequestTrasferAction += OnTransferRequested;
TM1.OnTrasferActionCompleted += OnTransferCompleted;
TM1.OnLotCompleted += OnLotCompleted;
Stage1.SetRecipeRootPath(@"D:\Stage1");
Stage1.OnRequestProcess += Stage1_OnRequestProcess;
LP1.OnRequestAction += LP1_OnRequestAction;
}
}
ITransferModule<T> members:
| Member | Description |
|---|---|
SetRule(TransferRule) | Set the scheduling strategy (e.g. TransferRule.PreferSwap) |
SetChildLocation(params string[]) | Declare virtual arm names within the module (e.g. "Upper", "Lower") |
Register(lotId, SubstrateJob[]) | Register a lot with its substrate route list |
Execute(lotId) | Start executing the registered lot |
ClearLot() | Clear the current lot from the scheduler |
IsCompleted(lotId) | Returns true when all substrates in the lot have completed |
NextRequest() | Advance the scheduler to the next pending transfer action |
OnRequestTrasferAction | Fired when the scheduler needs a physical robot move |
OnTrasferActionCompleted | Fired when a robot action completes |
OnLotCompleted | Fired when all substrates in the lot are done |
OnSameLocationProcess | Fired when a substrate needs in-place processing |
DualArmAction members (callback argument for OnRequestTrasferAction / OnTrasferActionCompleted):
| Member | Type | Description |
|---|---|---|
ActionType | ArmActionType | UpperGet, UpperPut, LowerGet, or LowerPut |
Target.Name | string | Destination location name |
Target.Index | int | Slot index within the location |
SubstarteKey | string | Substrate identifier |
ILoadModule members:
| Member | Description |
|---|---|
OnRequestAction | Fired when the scheduler requests a load or unload action; argument is LoadPortActionArgs |
IProcessModule members:
| Member | Description |
|---|---|
SetRecipeRootPath(path) | Set the root directory for recipe files |
OnRequestProcess | Fired when the scheduler delivers a substrate for processing; argument is ProcessArgs |
TransferScore
[TransferScore] decorates methods that return an int priority score. The scheduler calls all score methods on each tick and uses the scores to select the best pick/place pair. Methods must be declared inside a [Flow] class and return int.
Constructor:
TransferScore(string location, Direction direction)
| Parameter | Type | Description |
|---|---|---|
location | string | Location name — must match the name of a [TMC], [LMC], or [PMC] property, or a virtual child location registered via SetChildLocation |
direction | Direction | Direction.In = score for picking FROM this location; Direction.Out = score for placing TO it |
Score convention:
| Return value | Meaning |
|---|---|
> 0 | Available — higher values are preferred |
0 | Not ready — skip this location this tick |
< 0 (e.g. -1) | Hard block — do not schedule this location under any condition |
// Arm scores — arms are always available
[TransferScore("Upper", Direction.In)] public int InUpper() => 1;
[TransferScore("Upper", Direction.Out)] public int OutUpper() => 1;
[TransferScore("Lower", Direction.In)] public int InLower() => 1;
[TransferScore("Lower", Direction.Out)] public int OutLower() => 1;
// Load port — available only when a FOUP is docked
[TransferScore("LP1", Direction.In)]
public int InLP1() =>
(Port.Get(portdic.LP1.LP_Status)?.String() ?? "") == "Loaded" ? 1 : 0;
// Stage — hard-blocked while gate is closed; pick-ready only when processing is done
[TransferScore("Stage1", Direction.In)]
public int InStage1() => GateOpen("Stage1") ? StageReady("Stage1") : -1;
[TransferScore("Stage1", Direction.Out)]
public int OutStage1() => GateOpen("Stage1") ? 1 : -1;
Direction values:
| Value | Description |
|---|---|
Direction.In | Pick — get substrate FROM this location |
Direction.Out | Place — put substrate TO this location |
Document Attributes
Attributes used for extracting data from Excel/Word documents and generating .page files and C# constant classes.
| Attribute | Target | Injected Type | Arguments | Description |
|---|---|---|---|---|
[Document] | class | — | key | Specifies source Excel/Word document path |
[Save] | method | — | filename | Specifies output file paths (.page, .cs) |
[ColumnHeader] | property | — | header | Maps to Excel column header |
[EntryKey] | property | — | — | Designates primary key column |
[EntryProperty] | property | — | — | Designates additional property column |
[EntryDataType] | property | — | — | Specifies SECS data type |
Document + Save
Converts an Excel/Word document into a .page file and a C# constants class. This is the approach used in the equipment project to generate device/io.page from IO_Map Ver2.2.docx.
Constructors:
Document(string key)
Save(params string[] filename)
ColumnHeader(string header)
| Attribute | Parameter | Type | Description |
|---|---|---|---|
[Document] | key | string | Document category key or source file path; used to identify the document source |
[Save] | filename | string[] | One or more output file paths — typically a .page file and a .cs constants file |
[ColumnHeader] | header | string | Excel column header name to map to this property; omit to match by property name |
Step 1: Define a model class that maps Excel columns to .page entry fields.
public class IOModel
{
[ColumnHeader, EntryProperty]
public string Pin_No { set; get; } = string.Empty;
[ColumnHeader, EntryProperty]
public string Port_NO { set; get; } = string.Empty;
[ColumnHeader, EntryKey] // This column becomes the entry Name
public string Description { set; get; } = string.Empty;
[ColumnHeader, EntryProperty]
public string Model { set; get; } = string.Empty;
[ColumnHeader, EntryProperty]
public string Bit_On { set; get; } = string.Empty;
[EntryDataType] // Default data type for all entries
public string DataType { set; get; } = "enum.OffOn";
}
| Attribute | Role |
|---|---|
[ColumnHeader] | Maps property to an Excel column by name |
[EntryKey] | Designates this column as the entry name (first field in .page) |
[EntryProperty] | Includes this column in the property:{...} JSON |
[EntryDataType] | Sets the data type field (second field in .page) |
Step 2: Define the document converter with [Document] and [Save].
[Document(@"D:\PORT\SampleArduinoLib\equipment\port\IO_Map Ver2.2.docx")]
public class IODocument
{
[Save(@"D:\PORT\SampleArduinoLib\equipment\port\device\io.page",
@"D:\PORT\SampleArduinoLib\equipment\port\io1.cs")]
public Document<IOModel> Convert(Document<IOModel> doc)
{
doc.ForEach(v => v.DataType = "enum.OffOn"); // Set all entries to enum type
doc.ForEach(v => v.Package = "DigitalIO.DI"); // Link all to DigitalIO.DI package
return doc;
}
}
Step 3: Register in your MainWindow to trigger conversion.
Port.Add<IODocument>(@"D:\PORT\SampleArduinoLib\equipment\port\IO_Map Ver2.2.docx");
Generated io.page:
Main_CDA_Pressure_Switch_Check enum.OffOn pkg:DigitalIO.DI property:{"Pin_No":"1","Port_NO":"X01.00","Model":"ISE40A-C6-R-F","Bit_On":"Sensing"}
Door_Lock_On_Check enum.OffOn pkg:DigitalIO.DI property:{"Pin_No":"6","Port_NO":"X01.05","Model":"G7SA-2A2B","Bit_On":"Lock"}
FFU1_Normal_Status enum.OffOn pkg:DigitalIO.DI property:{"Pin_No":"15","Port_NO":"X01.14","Model":"MS-FC300","Bit_On":"Normal"}
Generated io1.cs:
// Auto-generated by Port. Do not edit manually.
namespace equipment
{
public static class Io1
{
public const string Main_CDA_Pressure_Switch_Check = "Main_CDA_Pressure_Switch_Check";
public const string Door_Lock_On_Check = "Door_Lock_On_Check";
public const string FFU1_Normal_Status = "FFU1_Normal_Status";
// ...
}
}
For more detailed usage, see the .NET Integration Guide.