ModuleEmulator Class |
Namespace: Demo3D.PLC.Rockwell.Emulator
public sealed class ModuleEmulator : IModuleEmulator, IDisposable
The ModuleEmulator type exposes the following members.
| Name | Description | |
|---|---|---|
| EventLock |
An object that you can lock to serialize access to the module emulator script functions.
| |
| IPAddress |
IP address of the device.
| |
| Properties |
Properties set by the module emulator factory.
Always null for RPI events.
|
| Name | Description | |
|---|---|---|
| AfterOutputs |
Calls all IAfterOutputs events.
| |
| BeforeInputs |
Calls all IBeforeInputs events.
| |
| ComputeInputs |
Calls all ComputeInputs events.
| |
| CopyFieldsToImage |
Copies data from the Module Emulator fields into the module image.
| |
| CopyFieldsToImage(DeviceArea) |
Copies data from the Module Emulator fields into the specified areas of the module image.
| |
| CopyImageToFields |
Copies data from the module image into the Module Emulator fields and properties.
| |
| CopyImageToFields(DeviceArea) |
Copies data from specified areas of the module image into the Module Emulator fields and properties.
| |
| FindAuto(Object) |
Find members with the AutoAttribute.
| |
| FindAutoT(Object) |
Find members with the AutoAttribute.
| |
| FindOrInstall |
Finds or installs a ModuleEmulator.
| |
| GetSystemTime |
Returns the device system time.
| |
| Install |
Installs a ModuleEmulator for a specified EDSInfo and connection point.
| |
| ProcessOutputs |
Calls all IProcessOutputs events.
| |
| ScheduleAfter |
Schedule an event.
| |
| ScheduleAt |
Schedule an event.
|
| Name | Description | |
|---|---|---|
| OnModuleEmulatorInstalled |
Occurs when a new ModuleEmulator is installed.
| |
| OnModuleEmulatorUninstalled |
Occurs when a ModuleEmulator is uninstalled.
|
The following example shows a simple 5094 IF8 Module Emulator
using System; using Demo3D.Common; using Demo3D.Net.Protocols; using Demo3D.PLC.Comms.CPF; using Demo3D.PLC.Rockwell.Emulator; namespace Examples.DeviceEmulation { /// <summary> /// 5094 IF8 device emulation. /// </summary> public class DE_5094_IF8 : IConstructRPI, IProcessOutputs { [Auto] ModuleEmulator moduleEmulator; [Auto] uint p_RunIdle; uint runIdle; ISystemTime systemTime; bool synchronized; class Channel : IComputeInputs, IBeforeInputs { readonly DE_5094_IF8 emulator; [Auto] float c_LowEngineering; [Auto] float c_HighEngineering; [Auto] float c_LowSignal; [Auto] float c_HighSignal; [Auto] float i_Data; [Auto, RPI] short i_RollingTimestamp; [Auto] float pi_Data; internal Channel(DE_5094_IF8 emulator) => this.emulator = emulator; // Called in response to updates from Emulate3D, to compute the values to send to the PLC. void IComputeInputs.ComputeInputs() { if (emulator.p_RunIdle == 0) return; // PLC is disconnected or in program mode var signalRange = c_HighSignal - c_LowSignal; var engineeringRange = c_HighEngineering - c_LowEngineering; i_Data = ((pi_Data - c_LowSignal) * (engineeringRange / signalRange)) + c_LowEngineering; } // Called in the IO process immediately before sending input to the PLC. void IBeforeInputs.BeforeInputs() { var isSynchronized = emulator.systemTime.IsSynchronized; i_RollingTimestamp = !isSynchronized ? (short)0 : (short)((emulator.systemTime.SystemTimeMicroseconds / 1000) & 0x7fff); } } [Auto] readonly Channel Ch00; [Auto] readonly Channel Ch01; [Auto] readonly Channel Ch02; [Auto] readonly Channel Ch03; [Auto] readonly Channel Ch04; [Auto] readonly Channel Ch05; [Auto] readonly Channel Ch06; [Auto] readonly Channel Ch07; // IO process construct method. void IConstructRPI.Construct(IComponentLogger logger) { systemTime = moduleEmulator.GetSystemTime(); } void IProcessOutputs.ProcessOutputs() { if (p_RunIdle != runIdle) { runIdle = p_RunIdle; if (runIdle != 0) moduleEmulator.ComputeInputs(); } } // Installs this device emulator into the Emulate3D device network emulator. public static IDisposable Install() { var if8 = new EDSInfo(DeviceVendor.Rockwell, DeviceType.RAMisc, productCode: 315, 0, 0); var mask = EDSMask.Vendor | EDSMask.DeviceType | EDSMask.ProductCode; return ModuleEmulator.Install(typeof(DE_5094_IF8), if8, mask); } } }
The following example shows a simple 5094 OB16 Module Emulator
using System; using Demo3D.Common; using Demo3D.PLC.Comms.CIP; using Demo3D.PLC.Comms.CIP.Nodes; using Demo3D.PLC.Comms.CPF; using Demo3D.PLC.Rockwell.Emulator; namespace Examples.DeviceEmulation { /// <summary> /// 5094 IF8 device emulation. /// </summary> public class DE_5094_OB16 : IConstructEmulator { [Auto] uint p_Status; [Auto] uint p_RunIdle; [AutoInstance(ClassID.TimeSync, 1)] TimeSync timeSync; class Point : IProcessOutputs { readonly DE_5094_OB16 emulator; bool oldProgMode; bool oldFaulted; ulong faultStartTime; bool faultFinalState; [Auto] bool c_ProgMode; [Auto] bool c_ProgValue; [Auto] bool c_ProgramToFaultEn; [Auto] bool c_FaultMode; [Auto] bool c_FaultValue; [Auto] byte c_FaultValueStateDuration; [Auto] bool c_FaultFinalState; [Auto] bool i_Data; [Auto] bool o_Data; internal Point(DE_5094_OB16 emulator) => this.emulator = emulator; public void ProcessOutputs() { // determine the current state var faulted = (emulator.p_Status & 1) == 0; var progMode = !faulted && emulator.p_RunIdle == 0; // if we faulted while in program mode, and c_ProgramToFaultEn is unset // then behave as if we're still in program mode if (faulted && oldProgMode && !c_ProgramToFaultEn) { faulted = false; progMode = true; } if (faulted) { // we're faulted // don't bother timing if the timer already expired, c_FaultFinalStateDuration is Forever, or we have no clock if (!faultFinalState && c_FaultValueStateDuration != 0 && (emulator.timeSync?.IsSynchronized ?? false)) { var timeNow = emulator.timeSync.SystemTimeMicroseconds; if (!oldFaulted) { // we just faulted, start timing faultStartTime = timeNow; } else { // we were already faulted, did the timer expire? var diffSeconds = (timeNow - faultStartTime) / 1000000; faultFinalState = diffSeconds >= c_FaultValueStateDuration; } } // faultFinalState is set when the c_FaultFinalStateDuration timer expired // otherwise if c_FaultMode, force the output to c_FaultValue if (faultFinalState) i_Data = c_FaultFinalState; else if (!c_FaultMode) i_Data = c_FaultValue; } else { // we're not faulted faultFinalState = false; if (progMode) { // we're in program mode // if c_ProgMode is unset, force the output to c_ProgValue if (!c_ProgMode) i_Data = c_ProgValue; } else { // running ok i_Data = o_Data; } } // remember last state oldProgMode = progMode; oldFaulted = faulted; } } [Auto] readonly Point Pt00; [Auto] readonly Point Pt01; [Auto] readonly Point Pt02; [Auto] readonly Point Pt03; [Auto] readonly Point Pt04; [Auto] readonly Point Pt05; [Auto] readonly Point Pt06; [Auto] readonly Point Pt07; [Auto] readonly Point Pt08; [Auto] readonly Point Pt09; [Auto] readonly Point Pt10; [Auto] readonly Point Pt11; [Auto] readonly Point Pt12; [Auto] readonly Point Pt13; [Auto] readonly Point Pt14; [Auto] readonly Point Pt15; public void Construct(MessageRouter module, IComponentLogger logger) { timeSync.PTPEnable = true; } // Installs this device emulator into the Emulate3D device network emulator. public static IDisposable Install() { var ob16 = new EDSInfo(DeviceVendor.Rockwell, DeviceType.GeneralPurposeDiscreteIO, productCode: 399, 0, 0); var mask = EDSMask.Vendor | EDSMask.DeviceType | EDSMask.ProductCode; return ModuleEmulator.Install(typeof(DE_5094_OB16), ob16, mask); } } }