Skip to main content
Version: Next

LMES Outbound Collection Logic Explanation

1. Introduction​

1.1. Document Purpose​

This document aims to elaborate on the internal implementation logic, technical architecture, and business process of the "Outbound Collection" function in the LMES system. It is mainly intended for technical developers, implementation consultants, and senior operation and maintenance personnel to help them deeply understand this functional module for secondary development, system configuration, and troubleshooting.

1.2. Scope of Application​

This document applies to the LMES Manufacturing Execution System, especially modules related to production execution and process management.

1.3. Core Concept Definitions​

  • Outbound: In MES, a business node indicating that a product or carrier has completed all scheduled operations such as processing and inspection at a certain station and is about to leave that station.
  • Collection: The action of obtaining data from sources such as equipment (e.g., PLC), sensors, scanners, or operator interfaces during the production process.
  • Process Engine: A core technical component used to automate and manage business processes. In this system, it dynamically executes, coordinates, and monitors each step of activity in the outbound process by parsing predefined flowcharts (PFD files).

2. PLC Interaction Sequence Diagram​

The following diagram clearly shows the detailed interaction sequence between LMES and PLC in a typical outbound process, including signal triggering, data reading and writing, and the final reset process.

2.1. Core Interaction Principle: Whoever Triggers, Resets​

The signal interaction between LMES and PLC strictly follows the "Whoever triggers, resets" principle. This means that if a signal is initiated by one party (e.g., changing from 0 to 1), then after the interaction is completed, the same party should be responsible for restoring it to the initial state (changing from 1 back to 0).

  • PLC Trigger: Outbound_FinishedSignal is set to 1 by the PLC to start the process, so after receiving the completion signal from LMES, it must also be reset to 0 by the PLC.
  • LMES Trigger: Outbound_CompletedSignal is set to 1 by LMES to notify the PLC that processing is complete, so after monitoring that the PLC has reset Outbound_FinishedSignal, it must also be reset to 0 by LMES.

This principle ensures that each interaction is a complete "handshake" process, avoiding confusion in signal states.


3. Core Process Variables Explanation​

The table below lists the Logical Variable Identifiers defined in the 10003.xml process template. These identifiers are standard names used internally by the process. They do not directly correspond to PLC addresses but need to be bound to the Variables predefined in the CMS base through the Process Management -> Station Configuration interface. The final PLC addresses are configured in the variables of the CMS base.

Logical IdentifierData TypeR/WDescription
Outbound_FinishedSignalintReadTrigger signal for PLC to notify LMES of processing completion. Value 1 starts the process. Must be reset to 0 by PLC after processing.
Outbound_SerialNumberVariablestringR/WUsed to transmit product serial number. LMES reads or writes back after association query.
Outbound_MaterialVariablestringReadWhen "Barcode Acquisition Method" is Material Association, LMES reads material code from this variable.
Outbound_TrayVariablestringReadWhen "Barcode Acquisition Method" is Pallet Association, LMES reads pallet code from this variable.
Outbound_QualityVariablestringReadWhen "Qualification Judgment Method" includes PLC Judgment, LMES reads the raw processing result given by PLC from this variable.
Outbound_ResultVariablestringWriteLMES distributes the final qualification judgment result to PLC (e.g., "1" for OK, "2" for NG).
Outbound_CompletedSignalintWriteSignal for LMES to notify PLC that the outbound process has been completed.
Outbound_FinishVariableintWriteLMES distributes the final result code of this outbound to PLC (see definition below).
Outbound_DescriptionstringWriteWhen an outbound exception occurs or is needed, LMES distributes specific text descriptions to PLC.

4. Business Logic and Configuration Guide​

4.1. Business Processing Sequence​

After receiving the Outbound_FinishedSignal=1 signal from the PLC, LMES strictly executes the business logic in the following order internally:

  1. Outbound Initialization (OutboundInitializeActivity): Prepare process environment, load product context.
  2. Parameter Collection (ParameterCollectActivity): Batch read all required process parameters and quality signals from PLC at once.
  3. Qualification Judgment (...QualificationJudgmentActivity): This is the core decision step.
    • PLC Judgment: Directly adopt the value of Outbound_QualityVariable.
    • Local Judgment: Compare collected parameters with formula specifications.
    • Composite Judgment: Execute both judgments above simultaneously, taking the strictest result.
  4. Parameter Storage (ParameterSaveActivity): Store all collected data and judgment results into the database to form a traceability record.
  5. Material Record (MaterialUsageRecordActivity): Record the materials consumed in this production.
  6. Result Distribution: Write values of result variables like Outbound_FinishVariable to PLC.

To correctly configure an outbound process, settings need to be made in the following modules:

  • Flow Management (FlowManagement):
    • Flow Definition File (10003_1.pfd): Defines the execution sequence, conditions, and activities of the outbound business logic. This file is the core template of the system, usually maintained by R&D personnel.
    • Flow Variable Configuration File (10003.xml): Defines the Logical Variable Identifiers required by the process. This file is also the core template of the system, usually maintained by R&D personnel.
  • Process Management (ProcessManagement):
    • Station Configuration: This is the most critical implementation configuration link. Here, you need to bind the Logical Variable Identifiers (such as Outbound_FinishedSignal) defined in the process template with the Variables already defined in the CMS base. LMES itself does not directly configure PLC addresses but indirectly achieves communication with equipment by referencing these base variables.
    • Define which Process Parameters the station needs to collect (ParameterCollectActivity will read these configurations).
    • Define which Defect Reasons and corresponding PLC signals the station has (PLCQualificationJudgmentActivity will use these configurations).
  • Formula Management (FormulaManagement):
    • Define the Process Parameter Standards (such as upper and lower limits) of the product at a certain station, which is the basis for LocalQualificationJudgmentActivity to perform local judgment.
  • Material Management (MaterialManagement):
    • Define the BOM list of the product, MaterialUsageRecordActivity will record material consumption based on this list.

5. Process Details​

This chapter will analyze the core logic of outbound collection in detail strictly based on the flowchart.

5.1. Start --> Finished Signal Listening​

  • Description: After the process starts, it enters the waiting state and continuously listens to the Outbound_FinishedSignal variable of the PLC. When the variable value becomes 1, the process is activated.
  • Implementation: Completed by the VariableMonitorActivity activity of the framework.

5.2. Barcode Acquisition Method (Conditional Branch)​

  • Description: The process decides how to obtain the product code based on the Outbound_ObtainBarcodeType configuration.
  • Branch 1 (Method=1): Directly read product code from Outbound_SerialNumberVariable.
  • Branch 2 (Method=2): Read material code from Outbound_MaterialVariable, query product code through MaterialAssociationActivity association, and then distribute product code back to PLC through VariableWriteActivity.
  • Branch 3 (Method=3): Read pallet code from Outbound_TrayVariable, query product code through TrayAssociationActivity association, and then distribute product code back to PLC through VariableWriteActivity.

5.3. Outbound Initialization​

  • Description: After obtaining the product identification, unified initialization operations are performed. If an exception occurs at this stage (e.g., product code is empty), the process will jump directly to the "Outbound Result Distribution" step and write an error code. If normal, continue.
  • Implementation: OutboundInitializeActivity (Business Activity).

5.4. Process Parameter Collection & Qualification Judgment​

  • Description: First, batch read all preset process parameters from PLC through ParameterCollectActivity. Then, enter different judgment branches according to the QualifiedJudgmentType configuration.
  • Branch 1 (Method=1): PLCQualificationJudgmentActivity directly adopts the PLC judgment result.
  • Branch 2 (Method=2): LocalQualificationJudgmentActivity performs comparison judgment internally in MES according to formula specifications.
  • Branch 3 (Method=3): CompositeQualificationJudgmentActivity combines the first two methods for composite judgment.

5.5. Process Parameter Storage​

  • Description: The judgment results of all branches eventually converge here. ParameterSaveActivity stores all collected data and judgment results into the database to form a traceability record. After this step is completed, it will trigger (SplitAND) the subsequent "Outbound Result Distribution" and "Material Usage Record" in parallel.
  • Implementation: ParameterSaveActivity (Business Activity).

5.6. Material Usage Record​

  • Description: Executed in parallel with result distribution, MaterialUsageRecordActivity is responsible for recording the material information consumed in this production.
  • Implementation: MaterialUsageRecordActivity (Business Activity).

5.7. Outbound Result Distribution​

  • Description: Distribute the final result to PLC and notify the SOP system. After this step is completed, it will also trigger (SplitAND) "Finished Signal Reset Listening" and "SOP Outbound Notification" in parallel.
  • Implementation: Result distribution is completed by the VariableWriteActivity activity of the framework.

5.8. SOP Outbound Notification​

  • Description: Executed in parallel with signal reset listening, SopControlActivity notifies the SOP display terminal of the outbound event.
  • Implementation: SopControlActivity (Business Activity).

5.9. Finished Signal Reset Listening & Outbound Completion​

  • Description: This is the final stage of the process. LMES waits for the PLC to reset Outbound_FinishedSignal to 0 through VariableMonitorActivity, which marks that the PLC has confirmed receipt of the outbound result.
  • Reset Processing Result: If the qualification judgment method is NOT pure PLC judgment (Method!=1), LMES will actively reset Outbound_ResultVariable to 0 through VariableWriteActivity.
  • Outbound Completion: Finally, LMES resets signal variables such as Outbound_CompletedSignal to 0 through VariableWriteActivity, returning the entire station to standby state, ready to welcome the next product.

5.10. End​

  • Description: Process ends normally.
  • Implementation: Marked by the EndActivity activity of the framework.

6. Core Business Activity Implementation Details​

This chapter aims to provide internal implementation details of core activities in the outbound process for secondary development or deep configuration personnel. It is worth noting that in all process activities related to station processes, complete configuration information of the current station can be obtained through Flow.DataItems.ApplicationData as ProcessModel.

6.1. OutboundInitializeActivity​

  • Flow Definition (PFD) Name: Outbound Initialization
  • Core Responsibility: Prepare all necessary context data for the outbound process.
  • Implementation Details:
    1. Reset State: Upon entering the activity, it will first clear/reset process variables related to this outbound, such as OutboundDescriptionValue and OutboundFinishSignal.
    2. Get Product Code: Check if FlowItemCollection.SerialNumber exists. If empty (e.g., upstream association query failed), it will immediately set an error result (e.g., NoProductEntry) and terminate the subsequent normal process.
    3. Load Context: If the product code exists, the activity will intelligently load the complete context of the product. It first checks if the current process instance already contains information such as Work Order (OrderModel), Product Model (ProductModel) (usually passed from the inbound process). If not, it calls the GetProductionAsync method to query the last production record of the product code from the database and uses it to restore key information such as its work order, product model, and inbound time.
  • Key Context Variables:
    • Read: SerialNumber, TrayCodeAssociationDescriptionValue, MaterialCodeAssociationDescriptionValue
    • Write: OutboundFinishSignal, OutboundDescriptionValue, OrderModel, ProductModel, InboundEntryTime
  • Secondary Development/Configuration Suggestions: This activity is the foundation of the process and usually does not need modification. But understanding its context loading mechanism (prioritizing current process data, then querying historical records) is crucial for troubleshooting.

6.2. ParameterCollectActivity​

  • Flow Definition (PFD) Name: Process Parameter Collection
  • Core Responsibility: Batch read all variable values related to this outbound from PLC.
  • Implementation Details:
    1. Build Variable List: The activity dynamically builds a list of PLC variable addresses to be read (varNames). The data source of this list is highly configurable, aggregating all the following points:
      • Process Parameters defined in station configuration (ProcessParameters).
      • Material Parameters defined in station configuration (MaterialParameters).
      • Formula Parameters defined in formula (FormulaParameters), including distribution and monitoring variables.
      • Some special variables hard-coded in the process, such as Outbound_QualityVariable.
    2. Batch Read: After building the list, it calls the IFlowVariableService.ReadValueAsync service to initiate a one-time batch read request to the data collection module.
    3. Store in Context: Store the returned dictionary containing all variable values (IReadOnlyDictionary<string, IVariableValue>) as a whole into the process context Flow.DataItems[FlowItemCollection.ParameterCollectData] for use by subsequent activities.
  • Key Context Variables:
    • Read: ApplicationData (Get ProcessModel)
    • Write: ParameterCollectData
  • Secondary Development/Configuration Suggestions: This activity is completely configuration-driven. If you need to collect a new PLC point as a Process Parameter, you only need to add the corresponding parameter definition in Process Management, without any code changes.

6.3. ...QualificationJudgmentActivity (Qualification Judgment Series)​

  • PLCQualificationJudgmentActivity (Flow Definition (PFD) Name: PLC Qualification Judgment):
    • Core Responsibility: Completely rely on the equipment's own judgment result.
    • Implementation Details: Logic is the simplest. It directly gets the value of Outbound_QualityVariable from ParameterCollectData. If the value is 1 or true, it is judged as qualified. If 2 or false, it further calls the GetUnqualifiedReasons method to check the Defect Reason variables in the station configuration to find out specifically which defect signal was triggered.
  • LocalQualificationJudgmentActivity (Flow Definition (PFD) Name: Local Qualification Judgment):
    • Core Responsibility: Complete quality judgment inside MES.
    • Implementation Details: Logic is the most complex. It will:
      1. Get the formula version of the current product (FormulaVersionModel).
      2. Traverse all Process Parameters in the station configuration.
      3. For each parameter, find its corresponding specification (lower, upper) in the formula version.
      4. Compare the actual value in ParameterCollectData with the specification.
      5. Any parameter out of tolerance will set the final result to unqualified and record the out-of-tolerance parameter name as the reason.
      6. Extension Point: This activity calls the implementation of the ILocalJudgmentStrategy interface, allowing developers to insert custom, non-standard (e.g., requiring complex calculation) qualification judgment logic through dependency injection.
  • CompositeQualificationJudgmentActivity (Flow Definition (PFD) Name: Composite Qualification Judgment):
    • Core Responsibility: Combine judgment results from PLC and MES.
    • Implementation Details: It does not contain independent logic but sequentially calls PLCJudgmentAsync and LocalJudgmentAsync methods, and then performs an "AND" operation on the two results. Only when both are qualified, the final result is qualified.
  • Key Context Variables:
    • Read: ParameterCollectData, OrderModel, ProductModel, FormulaApplyModel
    • Write: QualityResultValue, QualityResultReason
  • Secondary Development/Configuration Suggestions: For complex quality judgment needs, the best practice is to implement the ILocalJudgmentStrategy interface instead of directly modifying activity code.

6.4. ParameterSaveActivity​

  • Flow Definition (PFD) Name: Process Parameter Storage
  • Core Responsibility: Assemble and persist the complete traceability record of this outbound.
  • Implementation Details:
    1. Data Aggregation: This is the core of the activity. It collects all necessary information from Flow.DataItems, including: product code, work order, product model, inbound time, completion time, final qualification judgment result, unqualified reason, operator, and all process parameters and material parameters in ParameterCollectData.
    2. Build Model: Assemble aggregated data into a TraceModel object.
    3. Handle Special Logic: It checks the interaction result of SOP and judges the data type of this traceability (TraceDataType), e.g., whether it is inspection data.
    4. Store in Context: Store the built TraceModel object back to Flow.DataItems[FlowItemCollection.TraceModel], so that subsequent activities like MaterialUsageRecordActivity can obtain complete traceability information.
  • Key Context Variables:
    • Read: ApplicationData, OrderModel, ProductModel, ParameterCollectData, QualityResultValue, QualityResultReason, InboundEntryTime
    • Write: TraceModel
  • Secondary Development/Configuration Suggestions: If you need to add extra custom fields to the traceability record, the most recommended way is to add them to the TraceModel.ExtraProperties dictionary. This can be implemented through a simple custom activity before this activity, or by directly modifying this activity to add.

7. Result Codes and Exception Troubleshooting​

7.1. Outbound Result Code Definition (Outbound_FinishVariable)​

LMES informs PLC of the final outbound processing result via the Outbound_FinishVariable variable. The meanings and values of these codes are defined by the ExitResultConfig.cs file and can also be viewed and customized in the Process Management -> Process Configuration -> Process Result Value Configuration interface.

CodeEnum NameDescription
0ResetReset
1OKNormal
6NoProductEntryProduct code acquisition exception
9NGOther exceptions
10MaterialCodeNotBoundProductCodeMaterial code not bound to product code
11TrayCodeNotBoundProductCodePallet code not bound to product code

7.2. Exception Troubleshooting Guide​

When problems occur in the outbound process, priority should be given to using system-provided visual debugging tools, followed by analyzing log files.

  • Use Station Console (Preferred): The LMES system provides a powerful Station Console for each station, which is the Preferred Tool for real-time monitoring and troubleshooting.

    • Core Advantages:
      • Real-time Log Stream: The console pushes all logs of the current station associated process in real-time, including flowlog (process logic log), tracelog (traceability data log), and warnlog (warning/error log), without manual file refresh.
      • Real-time Variable Monitoring: Can see current values and changes of all PLC variables defined in the process in real-time.
      • Process Status Visualization: Can clearly see if the current process is running, stopped, or in an exception state.
      • Remote Control: Allows operators or engineers to perform operations like "Reset" on the process directly from the interface for quick recovery.
    • Troubleshooting Steps:
      1. Open the console of the corresponding station.
      2. Observe the Warning Log window for red error messages.
      3. Switch to the Process Log window to view detailed steps of process execution, locate the last successfully executed log, and thus judge the problem point.
      4. Observe the Variable Monitoring area to check if PLC signals change as expected.
  • Analyze Log Files (Offline/Advanced): If the console is inaccessible, or offline deep analysis is needed, it is recommended to use the LMES Log Quick Troubleshooting and Positioning Analysis Tool (LMES Studio). For specific usage, please refer to document doc/LMES Log Analysis Tool User Manual.md. If this tool cannot be used, you can also view raw log files directly on the server.

    • Use Process Instance ID: Searching for 【Instance=...】 (e.g., 【Instance=721876340764】) in logs can precisely link all relevant logs of a single process execution. This is a more precise tracking method than product code.
    • Search Product Code: Directly searching for the problematic product serial number can locate relevant processing records but may contain logs of multiple process executions.
    • Common Log Keywords:
      • Exception Reason:: This is the most direct error information, usually clearly pointing out the problem.
      • LogExceptionMessage: Searching this keyword can find exception stack information at the code level.
      • Qualified Signal: Searching activity name "PLC Qualification Judgment" can view whether the raw qualified signal value read from PLC meets expectations.
      • Parameter Range: Searching activity name "Local Qualification Judgment" can see the set range and actual collected value of each parameter, facilitating troubleshooting of which parameter is out of tolerance.
      • Store Parameter:: Searching activity name "Process Parameter Storage" can see the complete traceability model finally stored in the database, confirming data correctness.
      • Unsubscribe: If the process is stuck, check if there are Unsubscribe logs to judge if there is a problem with the variable monitoring part.

Through the above information, you can efficiently configure, understand, and troubleshoot the outbound process.


8. Advanced Secondary Development​

For scenarios requiring deep customization or adding extra logic without modifying existing activity code, the process engine provides two powerful extension methods: IFlowProcessor interceptor and IMethodExecuter custom function.

8.1. IFlowProcessor: Global Process Interceptor​

IFlowProcessor is an interface defined under the CMS.Plugin.FlowManagement.Abstractions namespace. Any class implementing this interface, as long as it is correctly registered in the dependency injection container, will be automatically discovered and executed by the process engine. It allows developers to inject custom code at specific lifecycle nodes of Every Activity execution in the process, implementing AOP (Aspect-Oriented Programming).

8.1.1. Core Interception Methods​

IFlowProcessor provides three core methods corresponding to three stages of activity execution:

  • OnEnterAsync(flowProcessor, sender, args): Called before any activity is about to Enter (execute its EnterAsync method).
  • OnExecuteAsync(flowProcessor, sender, args): Called before any activity is about to Execute (execute its ExecuteAsync method). This is the most commonly used interception point for processing core business logic.
  • OnExitAsync(flowProcessor, sender, args): Called before any activity is about to Exit (execute its ExitAsync method).

8.1.2. How to Use​

Through sender as Activity, developers can get the currently executing activity instance, knowing the activity's Type and Name. Through args as ProcessflowEventArgs, the complete process context DataItems can be accessed. Among them, DataItems.ApplicationData stores the complete configuration of the current station, which can be safely cast to ProcessModel type for access: var processModel = (args as ProcessflowEventArgs).DataItems.ApplicationData as ProcessModel;.

This allows developers to implement very flexible logic, such as:

  • Modify Process Context: Dynamically add, modify, or delete variables in DataItems before and after specific activity execution.
  • Add General Validation: Implement an IFlowProcessor to judge in OnExecuteAsync that if the current activity is ParameterSaveActivity, execute a piece of general, cross-process data validation logic before it executes.
  • Dynamic Logging: Automatically record more detailed diagnostic logs upon entry and exit for specific types of activities.

8.2. IMethodExecuter: Define Custom Process Functions​

The second more direct way of secondary development is implementing the IMethodExecuter interface. Unlike IFlowProcessor as a global interceptor, IMethodExecuter allows developers to create Explicitly Callable, named custom "methods" or "functions". These functions are usually triggered by MethodActivity in the process.

8.2.1. IMethodExecuter Interface Analysis​

This interface is designed for creating reusable independent business logic blocks. Its core members are as follows:

  • ExecuterName (Property): string type, must provide a Unique Name. This name is the identifier of the method executor, and the process calls it by this name.
  • Execute(ProcessflowEventArgs args) (Method): This is the core method of the executor. When the process calls this executor, this method is triggered.
    • args: Provides access to the process complete context DataItems, allowing you to read input parameters and write return values.
    • Return Value: Task<Dictionary<string, object>>. You can put calculation results into a dictionary and return it. The process engine will automatically update these key-value pairs to the process context DataItems.

8.2.2. Working Mechanism​

  1. Develop: Developers create one or more classes implementing the IMethodExecuter interface.
  2. Register: Register these implementation classes into the dependency injection container.
  3. Configure: In the process designer interface, implementers can drag a MethodActivity activity onto the canvas. In the activity's property configuration, the ExecuterName field will display all registered IMethodExecuter implementations in the form of a Dropdown List. Implementers only need to select the required executor, without manually entering the name.
  4. Execute: When the process runs to that MethodActivity, the engine finds the corresponding IMethodExecuter instance based on the name and calls its Execute method. After execution, the returned dictionary will be merged into the process context.

8.2.3. Use Case: Complex Material Traceability Code Parsing​

Suppose a key material's QR code contains very complex combination information (e.g., VendorCode-BatchNumber-ProductionDate-LineNumber) and needs to be parsed and written to different PLC variables respectively.

  1. Create Executor:
    public class BarcodeParsingExecuter : IMethodExecuter
    {
    public string ExecuterName => "ParseComplexMaterialBarcode";
    public string ExecuterDescription => "Parse complex material traceability code";

    public Task<Dictionary<string, object>> Execute(ProcessflowEventArgs args)
    {
    var context = args.DataItems;
    var complexBarcode = context["ScannedMaterialBarcode"] as string;
    var result = new Dictionary<string, object>();

    if (!string.IsNullOrEmpty(complexBarcode))
    {
    var parts = complexBarcode.Split('-');
    if (parts.Length == 4)
    {
    result["ParsedVendorCode"] = parts[0];
    result["ParsedBatchNumber"] = parts[1];
    result["ParsedProductionDate"] = parts[2];
    result["ParsedLineNumber"] = parts[3];
    }
    }

    // Returned result is automatically merged into process context
    return Task.FromResult(result);
    }
    }
  2. Use in Process:
    • Add a MethodActivity after ParameterCollectActivity and set its ExecuterName to ParseComplexMaterialBarcode.
    • Add a VariableWriteActivity after this MethodActivity, which can directly read variables like ParsedVendorCode, ParsedBatchNumber from the process context and write them to corresponding PLC addresses.

Through IMethodExecuter, complex logic closely related to specific business can be encapsulated and called by process designers as a "black box", greatly improving process readability and system maintainability.


8.3. Secondary Development Scenario Practice: Collect Extended Field and Store in Traceability Record​

This is a very common secondary development requirement: A project needs to collect a custom data outside the standard process (e.g., ambient temperature, equipment running duration, etc.) and store it in the product's traceability record, but without modifying any standard business activity (Activity) code.

Goal: When entering the "Process Parameter Storage" (ParameterSaveActivity) activity, read an extra "Ambient Humidity" variable from PLC and store it in the ExtraProperties of the traceability record.

Scheme: Use IFlowProcessor to intercept when ParameterSaveActivity is about to enter, completing data collection and context injection. Choosing the OnEnterAsync interception point is best practice because it ensures all external data is ready before the activity's core logic executes.

Step 1: Create IFlowProcessor Implementation Class​

First, create a new C# class implementing the IFlowProcessor interface.

using CMS.Plugin.FlowManagement.Abstractions;
using CMS.Plugin.MesSuite.Abstractions.Models;
using Microsoft.Extensions.DependencyInjection;
using SYC.Flow.Kernel;
using Volo.Abp.Data;

namespace MyCompany.MyProject.FlowProcessors;

public class ExtraDataCollectionProcessor : IFlowProcessor
{
// Use OnEnterAsync to intercept when activity enters
public async Task OnEnterAsync(FlowProcessor flowProcessor, object sender, EventArgs args)
{
// 1. Judge if current activity is "Process Parameter Storage"
if (sender is ParameterSaveActivity saveActivity)
{
var eventArgs = args as ProcessflowEventArgs;
if (eventArgs == null) return;

var context = eventArgs.DataItems;
var serviceProvider = eventArgs.ServiceProvider;

// 2. Get variable service from service container
var variableService = serviceProvider.GetRequiredService<IFlowVariableService>();

// 3. Read custom PLC variable (assume bound in station configuration)
var humidityVarName = "Custom_Ambient_Humidity"; // Custom logical variable name
var readResult = await variableService.ReadValueAsync(saveActivity, humidityVarName);
var humidityValue = readResult?.Value?.ToString();

// 4. Get or create ExtraProperties dictionary
var extraPropertiesKey = $"{FlowItemCollection.TraceModel}_ExtraProperties";
var extraProperties = context[extraPropertiesKey] as ExtraPropertyDictionary
?? new ExtraPropertyDictionary();

// 5. Add collected humidity value to dictionary
extraProperties["AmbientHumidity"] = humidityValue;

// 6. Write updated dictionary back to process context
context[extraPropertiesKey] = extraProperties;
}
}
}

Step 2: Register Interceptor to Dependency Injection System​

To let the process engine discover and use the ExtraDataCollectionProcessor we created, we need to register it into the application's Dependency Injection (DI) container. This is usually done in the ConfigureServices method of the project's module class (e.g., MyProjectModule.cs).

public override void ConfigureServices(ServiceConfigurationContext context)
{
// ... Other service registrations

// Register custom flow processor as singleton
context.Services.AddSingleton<IFlowProcessor, ExtraDataCollectionProcessor>();
}

Step 3: Configure Variable Binding in Station​

The last step is to let the system know which real PLC humidity address Custom_Ambient_Humidity corresponds to.

  1. Enter Process Management -> Process Configuration -> Process Parameters, create a new process parameter, e.g., named "Ambient Humidity".
  2. Enter Process Management -> Station Configuration, find the station that needs to apply this logic.
  3. In the station's parameter configuration, bind the newly created "Ambient Humidity" parameter with the logical name Custom_Ambient_Humidity used in our code.
  4. Finally, bind this logical identifier Custom_Ambient_Humidity to the Variable in the CMS base pointing to the actual PLC humidity address.

Conclusion​

After completing the above three steps, the entire process achieves non-intrusive logic extension. When the outbound process of any station runs to the "Process Parameter Storage" activity:

  • Our ExtraDataCollectionProcessor will be automatically triggered when this activity Enters.
  • It reads extra humidity sensor data.
  • Cleverly "stuffs" the data into the ExtraProperties of the traceability model about to be saved.
  • When ParameterSaveActivity executes its core logic later, it doesn't know the existence of this extended property, but it will faithfully save the entire TraceModel including our custom data to the database.

This method greatly guarantees the stability of core code while providing high flexibility for secondary development.