Giter VIP home page Giter VIP logo

libplctag.net's Introduction

libplctag - a C library for PLC communication

OS Architecture/CPU Version 64-bit 32-bit
Ubuntu x86, Arm 18.04 Supported Supported
Windows x86, Arm 10 (Server 19) Supported Supported
macOS x86, Arm 11 Supported Not Supported

libplctag CI

libplctag is an open source C library for Linux, Windows and macOS using EtherNet/IP or Modbus TCP to read and write tags in PLCs. The library has been in production since early 2012 and is used by multiple organizations for many tasks including controlling radio telescopes, large and precision manufacturing, controlling fitness equipment, food handling and many, many more.

Current Stable Version: 2.5

Old Stable Version: 2.4

WARNING - DISCLAIMER

Note: PLCs control many kinds of equipment and loss of property, production or even life can happen if mistakes in programming or access are made. Always use caution when accessing or programming PLCs!

We make no claims or warrants about the suitability of this code for any purpose.

Be careful!

Get It

Do you know what you want already? Download it from the releases page!

Features

High Level Features

  • EtherNet/IP and Modbus TCP support.
  • Open source licensing under the MPL 2.0 or LGPL 2+.
  • Pure C library for portability across Linux, Windows and macOS as well as 32-bit and 64-bit.
  • Support for x86, ARM and MIPS, and probably others.
  • Very stable API with almost no changes other than feature additions since 2012.
  • Low memory use and very high performance and capacity. Uses protocol-specific features to increase performance.
  • Simple API with minimal use of language-specific data to enable easy wrapping in other languages.
  • Extensive example programs showing use of all library features.
  • Wrappers for higher level languages like C#/.Net, Julia etc.
  • Free!

Detailed Features

PLC Support

  • support for Rockwell/Allen-Bradley ControlLogix(tm) PLCs via CIP-EtherNet/IP (CIP/EIP or EIP).
    • read/write 8, 16, 32, and 64-bit signed and unsigned integers.
    • read/write single bits/booleans.
    • read/write 32-bit and 64-bit IEEE format (little endian) floating point.
    • raw support for user-defined structures (you need to pull out the data piece by piece)
    • read/write arrays of the above.
    • multiple-request support per packet.
    • packet size negotiation with newer firmware (version 20+) and hardware.
    • tag listing, both controller and program tags.
  • support for Rockwell/Allen-Bradley Micro 850 PLCs.
    • Support as for ControlLogix where possible.
  • support for older Rockwell/Allen-Bradley such as PLC-5 PLCs (Ethernet upgraded to support Ethernet/IP), SLC 500 and MicroLogix with Ethernet via CIP.
    • read/write of 16-bit INT.
    • read/write of 32-bit floating point.
    • read/write of arrays of the above (arrays not tested on SLC 500).
  • support for older Rockwell/Allen-Bradley PLCs accessed over a DH+ bridge (i.e. a LGX chassis with a DHRIO module) such as PLC/5, SLC 500 and MicroLogix.
    • read/write of 16-bit INT.
    • read/write of 32-bit floating point.
    • read/write of arrays of the above.
  • extensive example code. Including
    • tag listing.
    • setting up and handling callbacks.
    • logging data from multiple tags.
    • reading and writing tags from the command line.
    • getting and setting individual bits as tags.
  • Support for Omron NX/NJ series PLCs as for Allen-Bradley Micro800.
  • Support for Modbus TCP.

Platform Support

  • CMake build system for better cross-platform support on Windows, Linux and macOS.
    • Native CMake support is present in recent versions of Microsoft Visual Studio.
  • Semantic versioning used and supported with specific library APIs for compatibility and feature checking.
  • C library has no dependencies apart from libc (and pthreads on some platforms).
  • Binary releases built for Ubuntu 18.04, macOS 10.15 and Windows 10. All 64-bit, with 32-bit binary releases for Windows and Ubuntu.
  • RaspberryPi supported. Both Linux and Windows IoT-based (some effort required to configure Visual Studio to build).

Alternate Programming Languages

The C library is designed for easy wrapping. Wrappers for many other languages include the following:

Code

How to Get The Code

The code for the core library is at libplctag. Stable code is on the default release branch. If you check out code from GitHub, it will default to the release branch.

If you want pre-built binaries, we have them available on the releases page. Just pick the one you want and download the ZIP file for your system. We have 32 and 64-bit builds for x86 Linux and Windows and 64-bit builds for x86-64 macOS.

Go to the main project at the libplctag organization to see the other wrappers. We are in a state of transition right now as we move more alternate language wrappers into the GitHub organization.

Example Code

Oh, wait, you want code! There are many examples in the examples directory.

A good place to start is simple.c.

This code reads several 32-bit signed integers (DINT), updates them, then writes them back out and rereads them from a tag named TestBigArray in a Logix-class Allen-Bradley PLC.

The README file in the examples directory describes some of the more interesting ones.

API

Most of the functions in the API are for data access. Direct support for single bits, 8-bit, 16-bit, 32-bit and 64-bit words (integer and floating point) are provided by the library.

See the API for more information.

Help Wanted

We need and welcome help with the following:

  • bug reports! We may not have your hardware so your bugs can help us make sure the library works in cases we cannot find!
  • bug fixes.
  • other protocols like Modbus, SBus etc.
  • other platforms like Android, iOS etc.
  • changes and additions for other PLCs.
  • additional compilers.
  • more language wrappers!
  • patches and updates for existing language wrappers!
  • Testing and more testing!

How to Contribute

We love contributions! Many users have contributed wrappers, extra functionality and bug fixes over the years. The library is much better for all the help that users have provided. We ask that your code contributions to the core library are under the same dual MPL/LGPL license.

Testing is difficult for us as we do not have access to all the different hardware out there. If you can, a great way to contribute is to test prereleases. These are on the prerelease branch! We appreciate all the help we get from our users this way.

The easiest way to contribute to the core library is to raise a PR on GitHub.

Wrappers in other languages are generally split off into separate projects. Those may have different licenses and contribution processes. Please look at the documentation for the wrapper in question.

History

See the wiki history page for more details on how libplctag was created and why we built it.

Contact and Support

There are two ways to ask for help or contact us.

libplctag Forum

If you have general questions or comments about the library, its use, or about one of the wrapper libraries, please join the Google group libplctag!

The forum is open to all, but is by request only to keep the spammers down. The traffic is fairly light with usually a small number of emails per month. It is our primary means for users to ask questions and for discussions to happen. Announcements about releases happen on the forum.

GitHub

If you find bugs or need specific features, please file them on GitHub's issue tracker for the main C library project. Each individual wrapper project has its own issue tracker.

If needed, we will initiate private communication from there.

License

See the license files (LICENSE.MPL or LICENSE.LGPL) for our legal disclaimers of responsibility, fitness or merchantability of this library as well as your rights with regards to use of this library. This code is dual licensed under the Mozilla Public License 2.0 (MPL 2.0) or the GNU Lesser/Library General Public License 2 or later (LGPL 2+).

This dual license applies to the core C library. Additional wrappers for other languages may be under different licenses. Please see those projects for more information.

Attributions and Trademarks

PLC5, SLC 500, MicroLogix, Micro8X0, CompactLogix and ControlLogix are trademarks of Rockwell/Allen Bradley. Windows and Visual Studio are trademarks of Microsoft. Apple owns the trademark on macOS.

Please let us know if we missed some so that we can get all the attributions correct!

End Note

Have fun and let us know if this library is useful to you. Please send test cases if you run into bugs. As PLC hardware is fairly expensive, we may not be able to test out your test scenarios. If possible, please send patches. We do not ask that you transfer copyright over to us, but we do ask that you make any submitted patches under the same licenses we use. We will not take any patches under the GPL license or licenses that are incompatible with the MPL 2.0 license.

We hope you find this library as useful as we do!

  • the libplctag team

libplctag.net's People

Contributors

bcurless1 avatar contibru avatar corentingallet avatar jfont-teg avatar jfontsaballs avatar jkoplo avatar timcantle avatar timyhac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libplctag.net's Issues

Tag group API

I wanted to break these out from #66 as that is getting a bit long!

Do you need to have constructors for tags within the TagGroup class? This seems like it may unnecessarily couple Tags and TagGroups. Perhaps I am missing something subtle here. At least in my mental model of this, Tags would be created independently and then grouped after they were created. My mental model also allows a Tag instance to be in more than one group at a time. It seems like that is possible here too.

On the read/write methods, does the break out of two kinds of async help? Perhaps I am just not seeing common use cases here. At least in my own code (the plural of anecdote is not data!), I either use blocking with a timeout or I do all the timeout management myself. The difference seems to be in the existence of the timeout parameter. What happens if you provide a timeout parameter? Does it automatically throw an exception on timeout? On the blocking method, what happens on timeout?

I am not used to C# async code, so if this model is a common idiom, then let me know and I'll shut up and go away :-)

Not Able to Get List of Tag in AB A

I am working on a project to get the list of tag available inside a AB PLC controller. The tag available is shown in the diagram below.
image

In this project, I am using ethernet connection to connect PLC with my laptop. The IP was 192.168.236.20. Below is the code that I deployed to get list of tags.

`var tags = new Tag<TagInfoPlcMapper, TagInfo[]>()
{
Gateway = "192.168.236.20",
Path = "1,0",
PlcType = PlcType.ControlLogix,
Protocol = Protocol.ab_eip,
Name = "TestDINTArray[0]"
};
tags.Read();

        ConsoleTable
            .From(tags.Value.Select(t => new
            {
                t.Id,
                Type = $"0x{t.Type:X}",
                t.Name,
                t.Length,
                Dimensions = string.Join(",", t.Dimensions)
            }))
            .Configure(o => o.NumberAlignment = Alignment.Right)
            .Write(Format.Default);`

However, when I run the program, I got nothing in result. What is the possible root cause of this?

Next steps for c# wrapper

We should determine what the next steps are for the c# wrapper now that it has been incorporated into the libplctag organization.

I feel a good place to start with is agreeing on what the goals should be. Maybe these could be similar goals to wrappers for other languages, maybe not. I have some goals written on the README for this project but definitely open to changing these goals.

One issue with the current goals is that we can simplify how this works because we no longer have to support the ability for end-users to supply their own plctag dll with statically linked projects.

Dispose Tag

Hi.
I started to uses your wrapper. In that time libplctag.0.0.27-alpha13 were latest release so is still in use on my side
Today I have some doubts if understand your examples, or there is some bug.

On simple example bellow I see that tag after .Dispose() has still status .isInitialized = true.
Is there a way how to Dispose, Release Tag ? Am i doing this in correct way ?

            Tag sStringOut_LEN = new Tag
            {
                Gateway = "192.168.7.100",
                Path = "1,0",
                PlcType = PlcType.ControlLogix,
                Protocol = Protocol.ab_eip,
                Name = $"PC_DATA.String_In.LEN",
                ElementSize = 4,
                ElementCount = 1
            };


            // Tag.isInitialized = false
            sStringOut_LEN.Initialize(5000);

            // Tag.isInitialized = true
            sStringOut_LEN.Read(5000);

            var someData = sStringOut_LEN.GetInt32(offset: 0);

            // Tag.isInitialized = true
            sStringOut_LEN.Dispose();

            // Tag.isInitialized = true   . Why ??

No timeout on async

During some testing I realized that if I attempt InitializeAsync or ReadAsync with no network connection to the PLC, it hangs indefinitely (no timeout).

Unreachable IP hangs indefinitely

While testing the examples I ran one that was trying to hit a tag at a 192 IP address. Instead of any sort of error message it simply sat in the StatusPending loop. I tried again and waited quite a bit to see if it would timeout, but no luck.

The examples run with a keyword default value for timeout on the tag constructors. I'm guessing this default value is infinity. However, there wasn't any device at the IP we were attempting to connect to so I would expect this to fail immediately and not wait on a timeout.

Extraction of native libraries fails for Windows Service

I haven't fully isolated this one, but I built a ASP.NET Core Windows Service and found out the hard way that it won't extract the plctag.dll during service startup.

I'm assuming this might be do to the permissions the service is running as. For now I just have to include plctag.dll in my build as a file.

Build script should tag releases

We've had a couple requests for source code for a particular release. I think Nuget will always be the primary way the package is consumed, but it's probably worth adding releases/tags to our build script.

SLC Strings - PLCTAG_ERR_TOO_SMALL

Is reading strings from a MicroLogix (SLC plc type) supported?

I'm reading from and writing to other data types fine, but when reading a string, e.g. ST102:0, I get the error PLCTAG_ERR_TOO_SMALL. Element size is 88, so seems right, confused why the error.

Embed libplctag binaries

Currently the consumer of this project must supply their own plctag.dll.

Ideally all they have to do is install this package from nuget and the dll copying is taken care of.

UDT Converter

I have a list of tag variable in an UDT as shown below. For such case, if I would like to create my own PlcMapper, is the code below correct? As the example used only involved in DINT, not SINT, therefore I would like to confirm if my written code is correct for this situation or not.

image

var DINT0 = tag.GetInt32(0)
var DINT1 = tag.GetInt8(4)
var DINT2 = tag.GetInt8(5)

MoveIndex = DINT0;

BitArray bitArray1 = new BitArray(new int[] { DINT1 });
MoveAbsPB = bitArray1[31];
OS_MoveAbs = bitArray1[30];
...

BitArray bitArray2 = new BitArray(new int[] { DINT2 });
OS_Jog = bitArray2[31];
SV_OnPB = bitArray2[30];
...

LibraryExtractor fails on Raspbian 10.

I'm having this error log when trying to get the plc tag on Raspbian 10.
The same app compiled for windows does not have this problem.

2020-11-26 14:43:56.994 -03:00 [ERR] System.TypeLoadException: This platform is not supported, could not load appropriate unmanaged library
   at libplctag.NativeImport.LibraryExtractor.GetResourceName()
   at libplctag.NativeImport.LibraryExtractor.ExtractAppropriateLibrary(String folder)
   at libplctag.NativeImport.LibraryExtractor.Init(Boolean forceExtract)
   at libplctag.NativeImport.plctag.ExtractLibraryIfRequired()
   at libplctag.Tag.Initialize()
   at libplctag.Tag`2.Read()

On the original libplctag documentation says that RaspberryPi is supported. Do it mean that libplctag.NET supports it too?
would plctag.ForceExtractLibrary = false; solve this issue?

The Os details are the following

  • OS: Raspbian GNU/Linux 10 (buster)
  • Kernel: Linux 5.4.51-v7+
  • Architecture: arm

The NuGet package is

  • libplctag 1.0.0
    thanks.

Make the Tag object use Generics

It feels like the Tag object should use a generic so that I can just new Tag<INT> and not have to know which special method to call when I do a read/return against that tag. We can keep the current Tag object as a base type and implement this on top.

Thoughts?

Contribute to libplctag organization?

I'm working with Kyle (libplctag author) to try to create a github organization for libplctag and the associated wrappers for different languages. I'm primarily a C# programmer and I was planning on starting from the Corsinvest wrapper to build up something a little more featureful that also included the newer features Kyle had added. However, I quickly realized the Corsinvest code is GPL3 and not particularly useful for me in a professional sense.

After some discussion, Kyle is planning on re-licensing libplctag under the MPL. This is a nice balance between some copyleft but still allowing for people to compile the code directly into other binaries.

Would you consider re-licensing your code as MPL and transferring it to the libplctag organization? I suppose it could also be kept as MIT if you feel strongly about it, but I'd prefer the MPL if I'm going to fork it. Also, would you be interested in helping maintain the C# wrapper within the organization going forward?

CancellationToken in InitializeAsync, ReadAsync and WriteAsync don't cancel the task after the time-out

First of all, thanks for the great work on libplctag and libplctag.NET.

#72 updated InitializeAsync, ReadAsync and WriteAsync but it did not update the 2 occurrences of token in the inner using:

using (token.Register(() => Abort()))
{
  while (GetStatus() == Status.Pending)
  {
    await Task.Delay(ASYNC_STATUS_POLL_INTERVAL, token);
  }
}

token should be replaced with cts.Token:

using (cts.Token.Register(() => Abort()))
{
  while (GetStatus() == Status.Pending)
  {
    await Task.Delay(ASYNC_STATUS_POLL_INTERVAL, cts.Token);
  }
}

to have the task canceled after the configured time out.

We know that Task.Delay() throws an TaskCanceledException when the time-out expires. Wouldn't it be better to catch the TaskCanceledException and throw a LibPlcTagException(Status.ErrorTimeout) instead?

using (cts.Token.Register(() => Abort()))
{
	while (GetStatus() == Status.Pending)
	{
		try
		{
			await Task.Delay(ASYNC_STATUS_POLL_INTERVAL, cts.Token);
		}
		catch (TaskCanceledException)
		{
			throw new LibPlcTagException(Status.ErrorTimeout);
		}
	}
}

PS: #96 might also be related to this issue, I experienced similar behavior while I was testing.

Publish to nuget

The primary goal of this project is to provide a package that is easy to consume for .NET projects. This means that publishing to nuget is high on the ToDo list.

Native runtime is not replaced on NativeImport package update

When a developer needs to make use of an update to the libplctag.NativeImport package that includes updated native runtimes, they will need to manually delete the existing plctag.dll/libplctag.so/libplctag.dylib.
New applications do not suffer from this issue because they will always extract the correct runtime.

NativeImport only replaces the runtime if it does not already exist on disk.
Furthermore, Visual Studio Build->Clean does not delete these files, it only deletes files it has created, so the developer must manually delete these files.

A separate, but related, issue is when application developers change their application's target platform. The target platform needs to match the native runtime architecture.

Some options

  • Always extract the runtime to disk rather than checking if it already exists (however this will prevent prototyping with pre-release runtimes).
  • Use nuget packaging with native runtimes (unclear if this will work across .NET Core and .NET Framework applications, and it will force the application developer to target a specific platform as opposed to using "Any CPU")
  • Provide an option to the application developer to choose whether to extract a runtime or use the one on the file system, this could be done by lazily extracting the appropriate library, allowing the application to first select whether to extract from assembly or use the runtime on disk.
    • A second option is to make the NativeImport plctag class a non-static class, but create a static instance on the LibPlcTag Utility class. This way users of the "friendly" API could also configure this behaviour.

Support .NET Framework

Currently does not support .NET Framework.

Workaround is to manually copy plctag.dll into same directory as libplctag.dll

Error on System.BadImageFormatException

Hi,

When I run .NET core project, the code is running fine. However, when I try to run on .NET framework project, it gave an error on this. I am running at "Any CPU" with an option "Prefer 32-bit" at ".NET Framework 4.7.2".

System.BadImageFormatException: 'An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)'

branch name and usage changes

Since I just managed to put a broken version of 2.1.7 out on master, I will take this a kick in the pants to actually redo my branch use that I've been thinking about for a while.

Starting soon (probably this weekend), I will create some new branches in the core library repo:

release - the real main branch. Nothing goes here except tested code that has "soaked" for a while as a pre-release unless it is an urgent bug fix or such a narrow change that the risk is small. I will make this the default branch so that when people check out the code without specifying a branch, this is what they get.

prerelease - once I am done with my development and tests, I will merge to prerelease. All prerelease drops will come from this branch. When these are validated with more testing and a lack of user bugs, I will merge this over to release.

I am not sure what to do with the master branch. I will try to keep it up to date with release for a while, but generally I would like to drop it.

How much heartburn will this give you guys?

Exception thrown when value in PLC is at the lower bound of the data type.

I'm getting an exception when I set a value in the PLC to the lower bound of the data type. For example, setting TestSINT.7 to 1 with all other bits set to 0 will result in this exception. I have had this happen with SINTs and DINTs. I haven't investigated if other data types have the same error. All other reads and writes are working fine, it's only when I have only the last bit set on a PLC tag.

Exception of type 'libplctag.LibPlcTagException' was thrown.

   at libplctag.Tag.GetInt8(Int32 offset)
   at libplctag.DataTypes.SintPlcMapper.Decode(Tag tag, Int32 offset)
   at libplctag.DataTypes.PlcMapperBase`1.DecodeArray(Tag tag)
   at libplctag.DataTypes.PlcMapperBase`1.libplctag.DataTypes.IPlcMapper<T[]>.Decode(Tag tag)
   at libplctag.Tag`2.DecodeAll()
   at libplctag.Tag`2.Initialize()
   at [MyMethod].ReadPLCData(LptLink link) in [MyMethod].cs:line 293

My ReadPLCData method just initializes the tag with a tagname passed in, reads it, and returns the data converted to an array of strings.

{libplctag.Tag<libplctag.DataTypes.SintPlcMapper, sbyte[]>}

Please let me know if you need any more information on how to recreate.

Issue with reading from Tag-Based alarms in a ControlLogix PLC

I found an issue with the original libplctag code where it would not allow you to read from tag-based alarm tags. I notified the original developers/supporters of libplctag library and they have fixed the issue. I reached out to the c# wrapper library developer on github and they are no longer supporting their code and pointed me to here.

Can you include the new changes to the libplctag to this wrapper so that people can read tag-based alarms?

Thanks,

Here is the original thread from the original libplctag git-hub.

libplctag/libplctag#222

Constructor Issues

The current class constructor provided by Tag is restrictive, and has the following issues:

  • Can't make use of asynchronous tag initialization (supported by core library)
  • Gateway is currently forced to be an IPAddress, but it can also be a hostname, or an IpEndPoint (i.e. with a port number). Hostnames are useful in DHCP scenarios.
  • There are many additional attributes used to support modbus usage (byte order).
  • Tag lister special tag name @tags does not take an element size or count, but the class forces the developer to use count of 1 if they don't supply another number - some string types might not work with a defined element size.
  • It forces the developer to supply a path, but Micro800 can not take a path.
  • In many scenarios, there will be a number of common properties among many tags (i.e. gateway).

The primary drive behind having constructor as it currently stands is to force the application developer to use the library properly, but a lot of validation is being done by the core library (and is now being flagged by copious status checking).

A proposal could be:

  • Reduce constructor to only require tag name
  • Make non-optional arguments (gateway, plctype) standard properties
  • Make other (optional) attributes nullable properties, only adding them to the attribute string if they are not null.
  • Move tag initialization out of the constructor into dedicated methods for initialization
  • Add a Plc class that acts as a Factory for tags and can inject the appropriate Plc information (gateway, path, etc) into the tags it creates.

Tag Datatype Validation

If you try to instantiate a tag with the proper Name but the wrong Datatype (ex. "SomeInt" as a DINT) the native.GetInt32() returns the minimum value to signify an error and liblctag.NET throws an exception with no message.

It'd be nice to improve on this behavior to help debug.

Good: "The tag definition is invalid"
Better: "Cannot call GetInt32 on an Int16 tag"

(Synchronous) Read/Write/Initialize with Timeout = 0 uses libplctag's non-blocking mode

When the native libplctag recieves a timeout value of 0, it interprets that as the user to use non-blocking mode.

The API that this wrapper exposes to its consumes indicates that when using Read/Write/Initialize they are using a synchronous (blocking) mode. There are dedicated methods suffixed with Async for the asynchronous mode.

Arguably, a timeout of 0 is incompatible with blocking methods because they will always take a non-zero amount of time.

Is this acceptable or should it throw a relevant exception?

Automated Tests

All the tests need to check for is that a DllNotFoundException isn't thrown, it doesn't need to communicate with a PLC.

Could supply a mock dll that implements the plctag interface but outputs to console or something.

PLC not connected Timeout doesn't seem to use the Timeout property of the tag.

When a PLC is disconnected, the Initialize method seems to take about 15 seconds to timeout. It seemed to me in the documentation of the code that it would use whatever value is set to the Timeout property. That Timeout property seems to work as expected for read/write timeouts if I unplug the PLC while my program is running, but it doesn't seem to for the first Initialize timeout if I start my program with the PLC disconnected.

DataType Enum Design

The design of the DataType class is unusual. Its main purpose currently is to provide element size of various Tag types.

Another time where Tag type is important is during Tag listing, where the underlying integer values are different as they refer to CIP types vs element size. (See this comment)

Is it possible to reduce the DataType to a basic enum (as opposed to a class of static values), and have some mapping elsewhere that provides the appropriate element size?

Proposal would be something like this:

public enum DataType
{
    SINT,
    INT,
    DINT,
    REAL,
    ....
}

The Tag constructor could take either a DataType enum or a data size (separate constructors).

Other concerns:

  • There are many other base types missing (LREAL, UINT, etc).
  • Should these use Pascal case (C# naming conventions) or just use upper case (AB naming convention).
  • Should other members appear that duplicate AB types (as they do now) (Int8, Int32, etc) - we took the stance for CpuTypes that there should only be one alternative for each unique thing.

Can .Net free unmanaged memory?

Sorry guys, dumb question: I am really close to figuring out how to dispose of C-style string data allocated in the native DLL for Java and I have been poking around a bit but my Google fu is weak today; can .Net do this too?

The reason I am asking is that I think I can make a C string API that is much, much easier to use than what I came up with before. But it requires that I return a newly allocated C string. Here is what the new string API would look like:

char *plc_tag_get_string(int32_t tag_id, int string_start_offset);
int plc_tag_set_string(int32_t tag_id, int string_start_offset, const char *string_val);
int plc_tag_get_string_capacity(int32_t tag_id, int string_start_offset);
int plc_tag_get_string_total_length(int32_t tag_id, int string_start_offset);

It is that first function that is the problem child. I have to allocate memory in order for this to really be easy to use. But then the caller needs to free it. I am about 99% certain that I have figured out how to do this in Java, I want to make sure that it can be done in .Net.

Can it be done without both of you tearing your hair out?

StringPlcMapper does not null out full string

One of my co-workers discovered this and it's a bit annoying.

The way we implemented the StringPlcMapper if you write a string like "12345" it will write a value of 5 to the string.len tag and then it will write 5 bytes into the actual byte array for the string.

The issue comes about if you then write a shorter string, "abc". The string.len will get updated to 3 and the first three bytes will be overwritten. BUT the value for the string array in the PLC will now be [a,b,c,4,5,\0,\0...] and this confuses some PLC functions and external programs.

StringPlcMapper.cs

I fixed this locally by creating a new, local mapper in my project that always writes the full max string length - padding it out with zeros. But it raises some questions:

  1. Are there any performance implications to writing extra bytes for strings?
  2. Should we do this for the different PLC types or only CLgx?
  3. Should this be optional functionality or default?

@kyle-github and @timyhac - What do you guys think?

Throwing exceptions

C# APIs generally throw errors rather than returning status codes. This ticket requests that all operations are checked for errors and then throw the appropriate Exception.

Provide tag listing example

This comes up every couple of weeks either in email directly to me or on the forum. I think it would be really great if someone could make an example in C# or VB that listed tags. I know that several users have used one of the C# wrappers and done this by looking at what the C code does.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.