OmronFinsNetStandard 2.0.0
dotnet add package OmronFinsNetStandard --version 2.0.0
NuGet\Install-Package OmronFinsNetStandard -Version 2.0.0
<PackageReference Include="OmronFinsNetStandard" Version="2.0.0" />
<PackageVersion Include="OmronFinsNetStandard" Version="2.0.0" />
<PackageReference Include="OmronFinsNetStandard" />
paket add OmronFinsNetStandard --version 2.0.0
#r "nuget: OmronFinsNetStandard, 2.0.0"
#:package OmronFinsNetStandard@2.0.0
#addin nuget:?package=OmronFinsNetStandard&version=2.0.0
#tool nuget:?package=OmronFinsNetStandard&version=2.0.0
OmronFinsNetStandard
Table of Contents
Introduction
OmronFinsNetStandard is a .NET Standard library that provides a straightforward and reliable way to communicate with Omron PLCs using the FINS (Factory Interface Network Service) protocol over Ethernet (TCP).
Designed for robust industrial applications, this library simplifies complex tasks such as connection management, handshake protocols, and memory access (Read/Write). It serves as a bridge between your .NET software and Omron PLCs, suitable for HMI development, data logging, or system integration.
Features
- 🚀 Connection Pooling: (New!) Automatically manages physical TCP connections. Multiple parts of your application can create client instances pointing to the same PLC without opening redundant sockets or causing conflicts.
- 🔒 Thread Safety: Built-in synchronization ensures that concurrent read/write operations from different threads are queued and executed safely, preventing data corruption.
- ⚡ Asynchronous Operations: Fully
async/awaitcompatible to keep your UI or control loops responsive during network I/O. - 🛡️ Robust Error Handling: Distinguishes between TCP transport errors and FINS protocol errors, providing detailed
FinsErrorcodes for easy troubleshooting. - 📝 Logging with NLog: Integrated logging allows for deep diagnostics of connection flows and data exchange.
- 🧩 Dependency Injection-Friendly: Lightweight client classes are perfect for DI containers and unit testing.
Installation
You can install the OmronFinsNetStandard package from NuGet:
dotnet add package OmronFinsNetStandard
Or via the NuGet Package Manager in Visual Studio:
Install-Package OmronFinsNetStandard
Usage
Connecting to the PLC
The library handles the FINS handshake automatically. Thanks to the internal connection manager, you can instantiate clients wherever needed.
using OmronFinsNetStandard;
// You can create a new instance for every operation if needed;
// the physical connection is reused under the hood.
using (var client = new EthernetPlcClient())
{
// Attempt to connect to the PLC at the given IP and port
// If a connection to 192.168.1.10 already exists, it will be reused.
bool isConnected = await client.ConnectAsync("192.168.1.10", 9600, timeout: 3000);
if (isConnected)
{
Console.WriteLine("Ready to communicate.");
}
else
{
Console.WriteLine("Failed to connect.");
}
}
Reading & Writing Bits
using OmronFinsNetStandard.Enums;
PlcMemory memory = PlcMemory.DM;
string bitAddress = "100.5"; // Format: "Word.Bit"
// 1. Reading a Bit
try
{
short bitState = await client.GetBitStateAsync(memory, bitAddress);
Console.WriteLine($"Bit State at {memory}{bitAddress}: {bitState}");
}
catch (FinsError ex)
{
Console.WriteLine($"Read failed: {ex.Message}");
}
// 2. Writing a Bit
try
{
// Set the bit to ON (1)
await client.SetBitStateAsync(memory, bitAddress, BitState.On);
Console.WriteLine($"Set {bitAddress} to ON.");
}
catch (FinsError ex)
{
Console.WriteLine($"Write failed: {ex.Message}");
}
Reading & Writing Words
using OmronFinsNetStandard.Enums;
PlcMemory memory = PlcMemory.DM;
ushort startAddress = 200;
ushort count = 5;
// 1. Reading Words
try
{
short[] data = await client.ReadWordsAsync(memory, startAddress, count);
Console.WriteLine($"Read {count} words from {memory}{startAddress}:");
Console.WriteLine(string.Join(", ", data));
}
catch (FinsError ex)
{
Console.WriteLine($"Error reading words: {ex.Message}");
}
// 2. Writing Words
try
{
short[] writeData = new short[] { 123, 456, 789 };
await client.WriteWordsAsync(memory, startAddress, writeData);
Console.WriteLine("Data written successfully.");
}
catch (FinsError ex)
{
Console.WriteLine($"Error writing words: {ex.Message}");
}
Reading Real Values
The library handles the conversion of 2 consecutive words into a standard float (Real).
using OmronFinsNetStandard.Enums;
ushort address = 300; // Reads words 300 and 301
try
{
float value = await client.ReadRealAsync(PlcMemory.DM, address);
Console.WriteLine($"Real Value at DM{address}: {value}");
}
catch (FinsError ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Exception Handling (FinsError)
The library throws FinsError exceptions for both network-level issues and PLC-level errors (e.g., protected memory,
address out of range).
try
{
// Intentionally reading from an invalid address
await client.ReadWordsAsync(PlcMemory.CIO, 9999, 1);
}
catch (FinsError ex)
{
Console.WriteLine($"❌ Error Occurred!");
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine($"MainCode: 0x{ex.MainCode:X2}, SubCode: 0x{ex.SubCode:X2}");
if (ex.CanContinue)
{
Console.WriteLine("Warning: Operation failed, but connection is still valid.");
}
else
{
Console.WriteLine("Critical Error: Connection might be compromised.");
}
}
Closing the Connection
await client.CloseAsync();
// or simply use 'using' statement as shown in the connection example.
Logging
OmronFinsNetStandard uses NLog to record diagnostic information. This is extremely useful for debugging FINS handshake issues or tracking data flow.
Enabling Logs in NLog
To enable logging, configure NLog in your application. Below is a sample configuration that logs to a file:
<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="[http://www.nlog-project.org/schemas/NLog.xsd](http://www.nlog-project.org/schemas/NLog.xsd)"
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](http://www.w3.org/2001/XMLSchema-instance)">
<targets>
<target xsi:type="Console" name="console"
layout="${time} | ${level:uppercase=true} | ${logger} | ${message} ${exception:format=tostring}" />
<target xsi:type="File" name="file" fileName="logs/plc_comm.log"
layout="${longdate}|${level}|${message}|${exception}" />
</targets>
<rules>
<logger name="OmronFinsNetStandard.*" minlevel="Debug" writeTo="console,file" />
</rules>
</nlog>
API Reference
EthernetPlcClient
ConnectAsync(string ipAddress, int port = 9600, int timeout = 5000): Establishes or reuses a thread-safe connection. Handles Ping and FINS Handshake.CloseAsync(): Decrements the usage counter for the connection; closes the socket if usage is zero.ReadWordsAsync/WriteWordsAsync: Bulk read/write operations for 16-bit integers.GetBitStateAsync/SetBitStateAsync: Read/write single bits.ReadRealAsync: Read 32-bit floating-point
PlcMemory (Enum)
Supported memory areas:
DM: Data MemoryCIO: CIO Memory (Core I/O)WR: Work Memory (Work Area)HR: Holding Relay (Holding Registers)AR: Auxiliary Relay (Auxiliary Area)
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a new branch (
git checkout -b feature/YourFeature). - Commit your changes (
git commit -m 'Add some feature'). - Push to the branch (
git push origin feature/YourFeature). - Open a Pull Request.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Contact
For questions or support, please open an issue on GitHub.
Happy coding! 🚀
| 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 | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | 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.1
- NLog (>= 5.3.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
- Implemented Connection Pooling: Reuses physical TCP connections for better performance.
- Added Thread Safety: Safe concurrent access from multiple threads.
- Improved Error Handling: Better distinction between TCP transport errors and FINS protocol errors.
- Refactored internal architecture while maintaining API compatibility.