<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jody Koplo</title>
    <description>The latest articles on DEV Community by Jody Koplo (@jkoplo).</description>
    <link>https://dev.to/jkoplo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F471378%2F664e8f24-aa77-4b21-9abf-6f55eab65342.jpeg</url>
      <title>DEV Community: Jody Koplo</title>
      <link>https://dev.to/jkoplo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jkoplo"/>
    <language>en</language>
    <item>
      <title>Introducing libplctag.NET 1.0.0 - PLC communications via C#/VB</title>
      <dc:creator>Jody Koplo</dc:creator>
      <pubDate>Mon, 21 Sep 2020 07:38:39 +0000</pubDate>
      <link>https://dev.to/jkoplo/introducing-libplctag-net-1-0-0-plc-communications-via-c-vb-2g5f</link>
      <guid>https://dev.to/jkoplo/introducing-libplctag-net-1-0-0-plc-communications-via-c-vb-2g5f</guid>
      <description>&lt;p&gt;We've released an open-source library that makes reading/writing tags to a PLC in C#/VB dead simple. It's available on &lt;a href="https://github.com/libplctag/libplctag.NET" rel="noopener noreferrer"&gt;Github&lt;/a&gt; and &lt;a href="https://www.nuget.org/packages/libplctag/" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Contents&lt;/strong&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;What is a PLC?&lt;/li&gt;
&lt;li&gt;What is libplctag?&lt;/li&gt;
&lt;li&gt;&lt;a href="//#libplctag.net"&gt;Why was libplctag .NET developed?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enough talk, let's see some code!&lt;/li&gt;
&lt;li&gt;What's next?&lt;/li&gt;
&lt;li&gt;All the Thank Yous&lt;/li&gt;
&lt;li&gt;Github Repo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is a PLC?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For those of us in the industrial automation world we often work with hardware called PLCs (Programmable Logic Controllers). These are the de facto standard for low level control in nearly any manufacturing line whether it's assembling cars, sorting packages, or filling soda bottles. Common brands include Siemens Simatic S7, Rockwell Automation Allen-Bradley CompactLogic/ControlLogix, and Schneider Modicon. The library we're introducing today primarily supports Rockwell Automation's Allen-Bradley line - everything from their oldest models up to the current CompactLogix an ControlLogix offerings.&lt;/p&gt;

&lt;p&gt;These PLCs use different and often proprietary methods of communicating over ethernet networks. In order to integrate them with the larger ecosystem of Manufacturing Operations Management it's required a Windows-based server running what's called an OPC server - essentially a protocol converter that reads/writes to the PLC using the proprietary protocol and makes it available to other systems over the standardized OPC protocol. Almost all OPC servers require a per installation license and often a license for the number of variables (tags in PLC lingo) you would like to read/write.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is libplctag?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The actual low-level library is called &lt;a href="https://github.com/libplctag/libplctag" rel="noopener noreferrer"&gt;libplctag&lt;/a&gt;. It's a portable C library with a low memory footprint that runs on Linux/Mac/Windows/Android. At present, the library handles all the low-level encoding and decoding of CIP (Common Industrial Protocol AKA Ethernet/IP) implemented in various Allen-Bradley PLCs. It also handles Modbus TCP and there are plans to include other protocols and PLCs in the future. The library itself has been around since 2012 and is quite stable and used in many applications.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why was libplctag .NET developed?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While C is a great language and very efficient, most programmers writing native or web applications rely on higher level languages. My language of choice is C#/dotnet these days and I've spent years using it to build programs that connect to PLCs and other industrial control systems. Unfortunately, these connections have always required either a commercially licensed C# library or an OPC server in order to communicate with the PLC. I started looking around for open-source options and came across the libplctag library via a couple of the C# wrappers that were floating around. None of the wrappers were very well documented and many were still using old versions of the lower level library. I reached out to the main C library developer and several of the wrapper maintainers to try to build a bigger community that I could help contribute to. Two of us got together, and with the help of the libplctag developer built a dotnet wrapper that includes all the features we wanted and thought should be expected in a dotnet library.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Available on Nuget&lt;/li&gt;
&lt;li&gt;Self-contained - C DLL is extracted as part of dotnet DLL&lt;/li&gt;
&lt;li&gt;Compatible with .Net Standard (Core/Framework)&lt;/li&gt;
&lt;li&gt;Cross platform (Windows/Mac/Linux)&lt;/li&gt;
&lt;li&gt;Strongly typed&lt;/li&gt;
&lt;li&gt;Support Async/Await* &lt;/li&gt;
&lt;li&gt;Usable in C# and Visual Basic .NET&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;* &lt;em&gt;await/async is currently stubbed into the API via Task.Run due to some complexities with the C callback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enough talk, let's see some code!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We've got quite a few &lt;a href="https://github.com/libplctag/libplctag.NET/tree/master/src/Examples/CSharp%20DotNetCore" rel="noopener noreferrer"&gt;examples&lt;/a&gt; in our Github repo, but I'll show a quick example below.&lt;/p&gt;

&lt;p&gt;The first thing to understand is that there must be a &lt;code&gt;Mapper&lt;/code&gt; class to convert from the PLC datatype to the dotnet datatype. Luckily, we've included mappers for all the base PLC types (DINT, SINT, STRING, BOOL, etc) and provided an &lt;a href="https://github.com/libplctag/libplctag.NET/blob/master/src/Examples/CSharp%20DotNetCore/SequencePlcMapper.cs" rel="noopener noreferrer"&gt;example&lt;/a&gt; for building a custom mapper for your own UDTs.&lt;/p&gt;

&lt;p&gt;Here's a simple example for reading/writing a DINT. Note that the &lt;code&gt;myTag.Value&lt;/code&gt; is typed as an &lt;code&gt;int&lt;/code&gt; and not an &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Instantiate the tag with the proper mapper and datatype&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myTag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DintPlcMapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"PROGRAM:SomeProgram.SomeDINT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Gateway&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"10.10.10.10"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1,0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PlcType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PlcType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControlLogix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ab_eip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Initialize the tag to set up structures and prepare for read/write&lt;/span&gt;
&lt;span class="c1"&gt;//This is optional as an optimization before using the tag&lt;/span&gt;
&lt;span class="c1"&gt;//If omitted, the tag will initialize on the first Read() or Write()&lt;/span&gt;
&lt;span class="n"&gt;myTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//The value is held locally and only synchronized on Read() or Write()&lt;/span&gt;
&lt;span class="n"&gt;myTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3737&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//Transfer Value to PLC&lt;/span&gt;
&lt;span class="n"&gt;myTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//Transfer from PLC to Value&lt;/span&gt;
&lt;span class="n"&gt;myTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//Write to console&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;myDint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myDint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Yeah, it's really that easy.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;What's next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We finished all of the work that we deemed &lt;em&gt;necessary&lt;/em&gt; for an initial release. However, there is always more development to do. Here's some features/fixes that are upcoming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;True async/await support from the lower libplctag library&lt;/li&gt;
&lt;li&gt;Background tag updates (read/writes on interval)&lt;/li&gt;
&lt;li&gt;Full discovery/listing of tags on a controller &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;All the Thank Yous&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This has been my first real foray into open-source and it's been entirely in my spare time - so of course thanks to my family for being patient with me.&lt;/p&gt;

&lt;p&gt;I was also really lucky to work with &lt;strong&gt;timyhac&lt;/strong&gt; - a great C# developer that lives on nearly the exact opposite side of the globe from me. Doing code reviews with someone you've never met is quite the experience.&lt;/p&gt;

&lt;p&gt;Finally, and most of all, I have to thank &lt;strong&gt;Kyle Hayes&lt;/strong&gt; for the incredible libplctag base library &lt;em&gt;and&lt;/em&gt; for being patient while the two C# devs asked all sorts of bothersome questions about C code and low level CIP protocol implementation.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Github Repo&lt;/strong&gt;
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/libplctag" rel="noopener noreferrer"&gt;
        libplctag
      &lt;/a&gt; / &lt;a href="https://github.com/libplctag/libplctag.NET" rel="noopener noreferrer"&gt;
        libplctag.NET
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A .NET wrapper for libplctag.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/libplctag/libplctag.NETassets/libplctag-logo.svg"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Flibplctag%2Flibplctag.NETassets%2Flibplctag-logo.svg" alt="libplctag" width="180"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;libplctag.NET&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/libplctag/libplctag" rel="noopener noreferrer"&gt;libplctag&lt;/a&gt; is an open source C library for Linux, Windows and macOS using EtherNet/IP or Modbus TCP to read and write tags in PLCs.&lt;/p&gt;

&lt;p&gt;libplctag.NET provides .NET wrapper packages for libplctag, and publishes them to Nuget.org.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;
&lt;a href="https://www.nuget.org/packages/libplctag/" rel="nofollow noopener noreferrer"&gt;libplctag&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/33ff0b11a409ffa1f71b887bb4de92cb106f5a22a52b9099c0132ce14cd33845/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f64742f6c6962706c63746167"&gt;&lt;img src="https://camo.githubusercontent.com/33ff0b11a409ffa1f71b887bb4de92cb106f5a22a52b9099c0132ce14cd33845/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f64742f6c6962706c63746167" alt="Nuget"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ccd8f879952a2805e9ee3ce831f5c719fd675507315dcaf017bc4a526a27440f/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f6c6962706c63746167"&gt;&lt;img src="https://camo.githubusercontent.com/ccd8f879952a2805e9ee3ce831f5c719fd675507315dcaf017bc4a526a27440f/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f6c6962706c63746167" alt="Nuget version"&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;This is the package intended for use in .NET applications
It provides an API for libplctag that should feel natural to .NET developers by supporting the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Values are strongly-typed (both Atomic types and User-Defined Types).&lt;/li&gt;
&lt;li&gt;Errors are thrown as Exceptions&lt;/li&gt;
&lt;li&gt;Async/Await&lt;/li&gt;
&lt;li&gt;Native resource cleanup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a href="https://github.com/libplctag/libplctag.NETexamples/" rel="noopener noreferrer"&gt;examples&lt;/a&gt; and &lt;a href="https://github.com/libplctag/libplctag.NETdocs/libplctag.md#getting-started" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; for more information.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;
&lt;a href="https://www.nuget.org/packages/libplctag.NativeImport/" rel="nofollow noopener noreferrer"&gt;libplctag.NativeImport&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9ddd2b4d332a2168084ca745b8b330f1fe5c4fb0e7c17fc23d9b3b95f879f230/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f64742f6c6962706c637461672e4e6174697665496d706f7274"&gt;&lt;img src="https://camo.githubusercontent.com/9ddd2b4d332a2168084ca745b8b330f1fe5c4fb0e7c17fc23d9b3b95f879f230/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f64742f6c6962706c637461672e4e6174697665496d706f7274" alt="Nuget"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7c7af8efe7990e6a36985e0bf80522ac95edd27e2322303a88d37ed57c105768/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f6c6962706c637461672e4e6174697665496d706f7274"&gt;&lt;img src="https://camo.githubusercontent.com/7c7af8efe7990e6a36985e0bf80522ac95edd27e2322303a88d37ed57c105768/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f762f6c6962706c637461672e4e6174697665496d706f7274" alt="Nuget version"&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;This package provides low-level (raw) access to the libplctag core library which is written in C.
The purpose of this package is to expose the API for this library to .NET applications, and handle platform and configuration issues.&lt;/p&gt;
&lt;p&gt;Application developers typically won't need to reference this package directly; it is primarily for use in other wrapper libraries.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/libplctag/libplctag.NET" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>news</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
