portdic 1.1.81
dotnet add package portdic --version 1.1.81
NuGet\Install-Package portdic -Version 1.1.81
<PackageReference Include="portdic" Version="1.1.81" />
<PackageVersion Include="portdic" Version="1.1.81" />
<PackageReference Include="portdic" />
paket add portdic --version 1.1.81
#r "nuget: portdic, 1.1.81"
#:package portdic@1.1.81
#addin nuget:?package=portdic&version=1.1.81
#tool nuget:?package=portdic&version=1.1.81
PortDic
PortDic is a comprehensive .NET library for industrial automation and communication systems. It provides standardized methods for interacting with industrial automation systems, equipment control, and data acquisition with support for multiple communication protocols.
About
PortDic package provides a complete framework for building industrial automation applications with:
- Annotation-Based Package System: Declarative programming model using attributes for package registration, API generation, and dependency injection
- Workflow and Flow Control: Sequential workflow execution with conditional watchers, timeouts, and notifications
- Protocol Integration: Support for SECS/GEM, MQTT, RTSP, and OPC UA protocols
- Real-time Data Management: Type-safe data setting and retrieval with event-driven architecture
- Broadcasting System: Multi-protocol communication management
- REST API Generation: Automatic endpoint creation from annotations
- Simple Communication Classes: High-performance asynchronous serial port and TCP communication with automatic reconnection
All features are designed for production use with comprehensive error handling, validation, and thread-safe operations.
Key Features
Annotation System
PortDic uses a comprehensive annotation system for declarative programming:
| Category | Annotations | Purpose |
|---|---|---|
| Package Management | [Package], [Flow], [Import] |
Class registration and dependency injection |
| Workflow Control | [Step], [Notify], [WatcherCompare], [WatcherAction], [Timeout] |
Workflow execution with conditional logic |
| API Endpoints | [API], [Command] |
REST API generation |
| Data Handling | [Property], [Mapping], [ModelProperty] |
Data management and transformation |
| Validation | [Valid] |
Data validation and business rules |
| Documentation | [Comment], [EnumCode] |
API documentation and enum exposure |
| Logging | [Logger] |
Dependency injection for logging services |
Core Capabilities
- Real-time Data Exchange: Type-safe data setting and retrieval with automatic type conversion
- Event-Driven Architecture: Comprehensive event handling for status changes, occurrences, and requests
- Package Injection: Automatic dependency resolution and inter-package communication
- Flow Control: Complex workflow management with conditional watchers and timeouts
- Protocol Support: Industrial communication protocols (SECS/GEM, OPC UA, MQTT, RTSP)
- Configuration Builder: Fluent interface for protocol configuration
- Performance Monitoring: Built-in profiling and monitoring capabilities
- Reference Model: Support for mapping multiple entry keys to reference objects
How to Use
Initialization and Setup
using portdic;
private static IPortDic portdic = Port.GetDictionary("sample");
private static GEM gem = portdic.BroadCast<GEM>();
public FormMain()
{
InitializeComponent();
// Register packages
portdic.Add<SampleFlow>("SampleFlow");
portdic.Add<Bulb>("Bulb1");
portdic.Add<Bulb>("Bulb5");
portdic.Add<Heater>("Heater1");
portdic.Add<Heater>("Heater5");
portdic.Add<Serial>("COM12");
// Register reference with mapping
[Import("Heater", "Heater6")]
public IReference reference;
portdic.Add(ref reference, new ReferenceModel()
{
{ "Temp1", Room1.RoomTemp1 },
{ "Temp2", Room1.RoomTemp2 },
});
// Event handlers
portdic.OnOccurred += Port_OnOccurred;
portdic.OnStatusChanged += Port_OnStatusChanged;
portdic.OnRequest += Port_OnRequest;
// GEM event handlers
gem.OnStatusChanged += Gem_OnStatusChanged;
gem.OnEvent += Gem_OnEvent;
gem.OnS2F37_EnableDisableEventReport += Gem_OnS2F37_EnableDisableEventReport;
gem.OnS10F5_TerminalDisplayMultiBlock += Gem_OnS10F5_TerminalDisplayMultiBlock;
gem.OnS2F33_DefineReport += Gem_OnS2F33_DefineReport;
gem.OnS6F11_EventReportSend += Gem_OnS6F11_EventReportSend;
gem.OnS3F17_CarrierActionRequest += Gem_OnS3F17_CarrierActionRequest;
gem.OnS7F1_ProcessProgramLoadInquire += Gem_OnS7F1_ProcessProgramLoadInquire;
// Start the Port system
portdic.Run();
}
Event Handling
Status Change Events
private void Port_OnStatusChanged(object sender, PortStatusArgs e)
{
switch (e.Status)
{
case PortStauts.Idle:
break;
case PortStauts.Executed:
break;
case PortStauts.Stopped:
break;
case PortStauts.Shutdown:
break;
case PortStauts.Failed:
break;
case PortStauts.Synchronized:
OnReady = true;
break;
}
}
Occurrence Events
private void Port_OnOccurred(object sender, PortEventArgs e)
{
switch (e.EventType)
{
case EventType.Reject:
Console.WriteLine(e.Message);
break;
// Other event types: Info, Warning, Error
}
}
Request Events
private void Port_OnRequest(object sender, PortRequestArgs e)
{
Console.WriteLine(string.Join(" ", e.Flags));
}
Package Development with Annotations
Basic Package Example
using portdatatype;
using portdic;
[Package]
public class Bulb
{
[Logger]
public ILogger Logger { get; set; }
[Property]
public IProperty Property { get; set; }
[API]
public string Comport
{
set
{
// Handle comport setting logic
Logger.Write($"Comport set to: {value}");
}
get
{
return comport;
}
}
[API(EntryDataType.Enum)]
public string OffOn
{
set
{
// Handle on/off state
}
get
{
return offon;
}
}
[Valid("Invalid bulb state")]
public bool Valid()
{
return true;
}
}
Package with Property Format
[Package]
public class Heater
{
[Logger]
public ILogger Logger { get; set; }
[Property]
public IProperty Property { get; set; }
[API(EntryDataType.Char)]
public string Power
{
set
{
Trace.WriteLine($"Power {value}");
}
get
{
return "12345678910";
}
}
[API(EntryDataType.Num, PropertyFormat.Json, "Unit")]
public double Temp
{
get
{
if (this.Property != null)
{
if (this.Property.TryToGetValue("Unit", out string unit))
{
if (unit == "F")
{
return (r.NextDouble() * 9 / 5) + 32;
}
else if (unit == "C")
{
return r.NextDouble();
}
}
}
return double.NaN;
}
}
[Valid("Invalid for connection")]
public bool Valid()
{
return true;
}
}
Workflow with Flow Control and Watchers
[Flow]
public class SampleFlow
{
[Notify]
public INotify Notify { get; set; }
[Step]
[WatcherCompare(Room1.Heater5Temp1, ">=", 50)]
[WatcherCompare(Room1.Heater5Temp2, ">=", 50)]
[WatcherAction(Room1.Bulb1OnOff5, "Off")]
[Timeout(0, 0)]
public void Step1()
{
Notify.Alert("hello ~~~~");
Task.Delay(1000).Wait();
Notify.Next();
}
[Step(nameof(Step1))]
[WatcherCompare(Room1.Heater5Temp1, "<", 50)]
[WatcherCompare(Room1.Heater5Temp2, "<", 50)]
[WatcherAction(Room1.Bulb1OnOff5, "On")]
[Timeout(0, 0)]
public void Step2()
{
Task.Delay(1000).Wait();
Notify.Next();
}
[Step(nameof(Step2))]
[WatcherCompare(Room1.Heater5Temp1, ">", 30)]
[WatcherCompare(Room1.Heater5Temp2, ">", 30)]
[WatcherAction(Room1.Bulb1OnOff5, "Off")]
[Timeout(0, 0)]
public void Step3()
{
Task.Delay(1000).Wait();
Notify.Next();
}
}
SET/GET Operations
// Setting values using entry key string
if (portdic.Set(selectKey.Text, setValue.Text))
{
MessageBox.Show($"Success: {selectKey.Text} = {setValue.Text}");
}
else
{
MessageBox.Show($"Failed: {selectKey.Text} = {setValue.Text}");
}
// Setting values using entry constants
portdic.Set(Room1.BulbOnOff, "On");
portdic.Set(Com12.Split, "0x0A");
portdic.Set(Com12.Message, "Hello");
// Getting values - returns string representation
string value = portdic.Get(entryKey)?.String();
string temp1 = portdic.Get(Room1.RoomTemp1)?.String();
// Setting flow actions
Port.GetDictionary("Sample").Set("SampleFlow", FlowAction.Executing);
Port.GetDictionary("Sample").Set("SampleFlow", FlowAction.Initialization);
// Alternative syntax
portdic["room1"].Set("BulbOnOff", "Off");
Entry Key Constants
Entry keys can be defined as constants for type-safe access:
public static class Room1
{
public const string BulbOnOff = "room1.BulbOnOff";
public const string RoomTemp1 = "room1.RoomTemp1";
public const string RoomTemp2 = "room1.RoomTemp2";
public const string Heater5Temp1 = "room1.Heater5Temp1";
// ... more entries
}
// Usage
portdic.Set(Room1.BulbOnOff, "On");
string temp = portdic.Get(Room1.RoomTemp1)?.String();
Protocol Integration
GEM (SECS/GEM) Integration
// Get GEM broadcast instance
private static GEM gem = portdic.BroadCast<GEM>();
// Or create with builder
var gem = portdic.BroadCast<GEM>(Port.CreateBuilder(BroadcastType.GEM)
.Mode(Mode.Active)
.Listen("127.0.0.1:5000")
.DeviceID("EQ001")
.T1(10).T2(5).T3(10)
.Build());
// Handle GEM events
gem.OnStatusChanged += (time, statustext) =>
{
Console.WriteLine(statustext);
};
gem.OnEvent += (time, eventtext) =>
{
Console.WriteLine(eventtext);
};
gem.OnS2F37_EnableDisableEventReport += (replier, message) =>
{
replier.Reply(message.SystemBytes, new ERACK(EventReportAcknowledge.Accepted));
};
gem.OnS2F33_DefineReport += (replier, message) =>
{
replier.Reply(message.SystemBytes, new ACKC(ACKC.Code.ACCEPTED));
};
gem.OnS10F5_TerminalDisplayMultiBlock += (replier, message) =>
{
replier.Reply(message.SystemBytes, new ACKC(ACKC.Code.ACCEPTED));
};
gem.OnS3F17_CarrierActionRequest += (replier, message) =>
{
var v = message.Deserialize<S3F17Message>();
// Process carrier action request
};
gem.OnS7F1_ProcessProgramLoadInquire += (replier, message) =>
{
var v = message.Deserialize<S7F11Message>();
// Process program load inquire
};
GEM Message Deserialization
public class S3F17Message
{
[SECS(0)]
public U2 DATAID { set; get; }
[SECS(1)]
public A CARRIERACTION { set; get; }
[SECS(2)]
public A CARRIERSPEC { set; get; }
[SECS(3)]
public B PORTNUMBER { set; get; }
[SECS(4)]
public S3F17MessageItem ITEMS { set; get; } = new S3F17MessageItem();
}
public class S3F17MessageItem
{
[SECS(0, MappingRule.ByKey)]
public B Capacity { set; get; }
[SECS(1, MappingRule.ByKey)]
public B SubstrateCount { set; get; }
[SECS(2, MappingRule.ByKey)]
public List<ContentMap> ContentMap { set; get; }
[SECS(3, MappingRule.ByKey)]
public List<U1> SlotMap { set; get; }
[SECS(4, MappingRule.ByKey)]
public A Usage { set; get; }
}
MQTT Integration
var mqtt = portdic.BroadCast<MQTT>(Port.CreateBuilder(BroadcastType.MQTT)
.Listen("127.0.0.1:1883")
.Users(new User("admin", "admin"))
.AllowRemotes("127.0.0.1")
.ClientId("PortClient")
.QoS(1)
.Build());
OPC UA Integration
var opcua = portdic.BroadCast<OPCUA>(Port.CreateBuilder(BroadcastType.OPCUA)
.Listen("opc.tcp://localhost:4840")
.ApplicationInfo("PortApp", "urn:PortApp", "urn:PortApp")
.SecurityConfig(SecurityMode.SignAndEncrypt, SecurityPolicy.Basic256Sha256)
.Credentials("admin", "password")
.Build());
Performance Monitoring
// Enable profiling
portdic.Profile();
// Performance test example
var t1 = DateTime.Now;
int count = 0;
while (count < 10000)
{
portdic.Set(Room3.BulbOnOff, "On");
count++;
}
var t2 = (DateTime.Now - t1).TotalMilliseconds;
Trace.WriteLine($"SPEND TIME: {t2} (ms)");
Simple Communication Classes
Serial Port Communication
using portdic.simple;
public class MySerial : AsyncSerial
{
public MySerial()
{
portName = "COM3";
baudRate = 9600;
delimiter = "\n";
this.DataReceived += (sender, message) =>
{
Console.WriteLine($"Received: {message}");
};
this.ReconnectSuccess += (sender, e) =>
{
Console.WriteLine("Reconnected successfully");
};
}
public override void LogWrite(string log)
{
Console.WriteLine(log);
}
}
// Usage
var serial = new MySerial();
await serial.ConnectAsync();
await serial.SendAsync("Hello World!");
TCP Server
using portdic.simple;
public class MyTCPServer : AsyncTCPServer
{
public MyTCPServer()
{
this.port = "5000";
this.ClientConnected += (sender, client) =>
{
Console.WriteLine($"Client connected: {client.RemoteEndPoint}");
};
this.DataReceived += async (sender, data) =>
{
Console.WriteLine($"Received from {data.Client.Id}: {data.Message}");
await this.SendToClientAsync(data.Client, "Echo: " + data.Message);
};
}
public override void LogWrite(string log)
{
Console.WriteLine(log);
}
}
// Usage
var server = new MyTCPServer();
await server.StartAsync();
// Broadcast to all clients
await server.BroadcastAsync("Server message");
TCP Client
using portdic.simple;
public class MyTCPClient : AsyncTCPClient
{
public MyTCPClient()
{
this.host = "127.0.0.1";
this.port = "5000";
this.Connected += (sender, e) =>
{
Console.WriteLine("Connected to server");
};
this.DataReceived += (sender, message) =>
{
Console.WriteLine($"Received: {message}");
};
this.ReconnectSuccess += (sender, e) =>
{
Console.WriteLine("Reconnected successfully");
};
}
public override void LogWrite(string log)
{
Console.WriteLine(log);
}
}
// Usage
var client = new MyTCPClient();
await client.ConnectAsync();
await client.SendAsync("Hello Server!");
Ring Buffer
using portdic.simple;
using System.Text;
// Create a ring buffer with capacity (must be power of 2)
var buffer = new RingBuffer<byte>(1024);
// Producer: Write data
byte[] data = Encoding.UTF8.GetBytes("Hello");
int written = buffer.Write(data);
// Consumer: Read data
byte[] output = new byte[1024];
int bytesRead = buffer.Read(output);
string message = Encoding.UTF8.GetString(output, 0, bytesRead);
// Single item operations
if (buffer.TryWrite(0x42))
{
if (buffer.TryRead(out byte value))
{
Console.WriteLine($"Read: {value}");
}
}
// Peek without consuming
if (buffer.TryPeek(out byte peekValue))
{
Console.WriteLine($"Peeked: {peekValue}");
}
Main Types
The main types provided by this library are:
Core Types
IPortDic: Main interface for port dictionary communication, real-time data exchange, and protocol managementPort: Factory class for creating port dictionary instancesPortDic: Core implementation of the port dictionary system
Annotation Attributes
[Package]: Attribute for marking classes as Port-managed packages[Flow]: Attribute for defining workflow classes[API]: Attribute for automatic REST API endpoint generation[Step]: Attribute for marking workflow steps[Import]: Attribute for dependency injection[Property]: Attribute for mapping properties to Entry Properties[Valid]: Attribute for data validation and business rules[Command]: Attribute for marking methods as command endpoints[Logger]: Attribute for dependency injection of logging services[Notify]: Attribute for workflow notification services[WatcherCompare]: Attribute for conditional workflow step execution[WatcherAction]: Attribute for automatic actions on workflow steps[Timeout]: Attribute for workflow step timeout configuration
Interfaces
IFlowControl: Interface for workflow control and navigationIStepTimer: Interface for timing and scheduling workflow stepsIReference: Interface for function references and collectionsINotify: Interface for workflow notifications and alertsILogger: Interface for logging servicesIProperty: Interface for property access and configurationIGemReplier: Interface for GEM message replies
Enums and Status Types
PortStauts: Port status enumeration (Idle, Executed, Stopped, Shutdown, Failed, Synchronized)EventType: Event type enumeration (Info, Warning, Error, Reject)FlowAction: Flow action enumeration (Executing, Initialization, etc.)EntryDataType: Entry data type enumeration (String, Num, Char, Enum, etc.)PropertyFormat: Property format enumeration (Json, etc.)
Simple Communication Classes
AsyncSerial: Abstract base class for asynchronous serial port communication with automatic reconnectionAsyncTCPServer: Production-ready asynchronous TCP server with client management and 24/7 stabilityAsyncTCPClient: High-availability asynchronous TCP client with automatic reconnectionClientContext: Represents the context for a connected TCP client, including connection information and message bufferingRingBuffer<T>: Lock-free, zero-allocation ring buffer for high-performance scenarios. Thread-safe for single producer and single consumer operations
Protocol Classes
GEM: SECS/GEM protocol implementationMQTT: MQTT protocol implementationOPCUA: OPC UA protocol implementationRTSP: RTSP protocol implementation
Additional Documentation
- PortDic .NET Integration Guide - Comprehensive documentation with examples
- System.IO.Ports Documentation
- System.Net.Sockets Documentation
Requirements
- .NET Standard 2.0 or higher
- System.IO.Ports package (for serial port functionality)
Related Packages
- System.IO.Ports - Required for serial port functionality
Feedback & Contributing
PortDic is released as open source. Bug reports and contributions are welcome. Please report issues and submit pull requests through the project repository.
For additional support and examples, refer to the PortDic Documentation.
License
Please refer to the license file included with this package for license information.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- CommunityToolkit.Mvvm (>= 8.4.0)
- FodyHelpers (>= 6.8.2)
- Microsoft.CSharp (>= 4.7.0)
- System.Collections.Immutable (>= 5.0.0)
- System.IO.Ports (>= 10.0.0)
- System.ServiceProcess.ServiceController (>= 9.0.3)
- System.Text.Json (>= 9.0.0)
- Tommy (>= 3.1.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on portdic:
| Package | Downloads |
|---|---|
|
Port.SDK
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.81 | 0 | 3/15/2026 |
| 1.1.80 | 41 | 3/10/2026 |
| 1.1.79 | 74 | 3/9/2026 |
| 1.1.78 | 84 | 3/2/2026 |
| 1.1.77 | 466 | 12/9/2025 |
| 1.1.76 | 457 | 12/8/2025 |
| 1.1.75 | 305 | 11/12/2025 |
| 1.1.74 | 308 | 11/11/2025 |
| 1.1.73 | 228 | 11/9/2025 |
| 1.1.72 | 201 | 10/14/2025 |
| 1.1.71 | 210 | 10/13/2025 |
| 1.1.70 | 148 | 10/12/2025 |
| 1.1.69 | 200 | 9/30/2025 |
| 1.1.68 | 176 | 9/28/2025 |
| 1.1.67 | 207 | 9/25/2025 |
| 1.1.66 | 211 | 9/23/2025 |
| 1.1.65 | 228 | 9/22/2025 |
| 1.1.64 | 242 | 9/21/2025 |
| 1.1.63 | 262 | 9/14/2025 |
| 1.1.62 | 208 | 9/10/2025 |