libplctag / libplctag.NET

A .NET wrapper for libplctag.
https://libplctag.github.io/
Mozilla Public License 2.0
221 stars 56 forks source link

SLC Strings - PLCTAG_ERR_TOO_SMALL #58

Closed IanRobo75 closed 4 years ago

IanRobo75 commented 4 years ago

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.

timyhac commented 4 years ago

Hi @IanRobo75 - thanks for trying this wrapper!

The wrapper should be able to support anything that the native runtimes support, so it could be possible libplctag native doesn't support this - I'm not really sure.

It is possible that the wrapper has some issues, you can make use of the libplctag.NativeImport package that provides raw access to the libplctag native functionality without any abstractions over the top - could be useful to try this.

Also, are you using the latest prerelease? These packages are still in alpha.

MicroLogic and SLC are different CPU types, could you try with both and see what the result is? https://github.com/libplctag/libplctag/wiki/Tag-String-Attributes

IanRobo75 commented 4 years ago

I see that the wrapper does not expose the MicroLogix CPU Type. I’ll look at using the NativeImport and investigate.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Monday, July 20, 2020 4:44 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Hi @IanRobo75https://github.com/IanRobo75 - thanks for trying this wrapper!

The wrapper should be able to support anything that the native runtimes support, so it could be possible libplctag native doesn't support this - I'm not really sure.

It is possible that the wrapper has some issues, you can make use of the libplctag.NativeImport package that provides raw access to the libplctag native functionality without any abstractions over the top - could be useful to try this.

Also, are you using the latest prerelease? These packages are still in alpha.

MicroLogic and SLC are different CPU types, could you try with both and see what the result is? https://github.com/libplctag/libplctag/wiki/Tag-String-Attributes

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-660798238, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY3MLTPIP5TTGOJZJPDR4PDQDANCNFSM4PB255VQ.

kyle-github commented 4 years ago

Sorry for the email response. One thing to try is a different size. I think strings on PCCC-based PLCs are either 82 or 84 bytes, not 88.

Best, Kyle

On Mon, Jul 20, 2020, 12:26 PM IanRobo75 notifications@github.com wrote:

I see that the wrapper does not expose the MicroLogix CPU Type. I’ll look at using the NativeImport and investigate.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Monday, July 20, 2020 4:44 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com

Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Hi @IanRobo75https://github.com/IanRobo75 - thanks for trying this wrapper!

The wrapper should be able to support anything that the native runtimes support, so it could be possible libplctag native doesn't support this - I'm not really sure.

It is possible that the wrapper has some issues, you can make use of the libplctag.NativeImport package that provides raw access to the libplctag native functionality without any abstractions over the top - could be useful to try this.

Also, are you using the latest prerelease? These packages are still in alpha.

MicroLogic and SLC are different CPU types, could you try with both and see what the result is? https://github.com/libplctag/libplctag/wiki/Tag-String-Attributes

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub< https://github.com/libplctag/libplctag.NET/issues/58#issuecomment-660798238>, or unsubscribe< https://github.com/notifications/unsubscribe-auth/AIY6RY3MLTPIP5TTGOJZJPDR4PDQDANCNFSM4PB255VQ>.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661287249, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN4LC2OI7XVMRQR5UN2YY3R4SK5RANCNFSM4PB255VQ .

IanRobo75 commented 4 years ago

Sorry for the email response. One thing to try is a different size. I think strings on PCCC-based PLCs are either 82 or 84 bytes, not 88. Best, Kyle On Mon, Jul 20, 2020, 12:26 PM IanRobo75 @.> wrote: I see that the wrapper does not expose the MicroLogix CPU Type. I’ll look at using the NativeImport and investigate. Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%] From: timyhac @.> Sent: Monday, July 20, 2020 4:44 PM To: libplctag/libplctag.NET @.> Cc: IanRobo75 @.>; Mention @.***> Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58) Hi @IanRobo75https://github.com/IanRobo75 - thanks for trying this wrapper! The wrapper should be able to support anything that the native runtimes support, so it could be possible libplctag native doesn't support this - I'm not really sure. It is possible that the wrapper has some issues, you can make use of the libplctag.NativeImport package that provides raw access to the libplctag native functionality without any abstractions over the top - could be useful to try this. Also, are you using the latest prerelease? These packages are still in alpha. MicroLogic and SLC are different CPU types, could you try with both and see what the result is? https://github.com/libplctag/libplctag/wiki/Tag-String-Attributes — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub< #58 (comment)>, or unsubscribe< https://github.com/notifications/unsubscribe-auth/AIY6RY3MLTPIP5TTGOJZJPDR4PDQDANCNFSM4PB255VQ>. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#58 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN4LC2OI7XVMRQR5UN2YY3R4SK5RANCNFSM4PB255VQ .

OK will do. I see the latest alpha has the MicroLogix PLC type as well, which was missing from the release version. So I'll try that as well.

timyhac commented 4 years ago

This is interesting - it means we will have to have different marshallers for different CPU types.

@jkoplo

IanRobo75 commented 4 years ago

OK, so I believe the base library does not easily support strings for PLC5/ SLC/ MicroLogix comms. I can read a string if I put the correct length in for the string (i.e. if the string in the PLC is "ABC" and I set the tag length as 3 then it works). Getting the length attribute dynamically is too hard for me and not worth the effort. For reference - I can read I, O, N files as integer (16 bit), and L files as Long (32 bit), but they have to have the N prefix (e.g. N100:1, N9:3 (for L9:3), N0:4 (for O:4), N1:5 (for I:5). B and F files are read as expected (e.g. B3:6, F8:7).

My next task is to communicate with a CompactLogix, I expect strings will be fine there.

kyle-github commented 4 years ago

So reads of DINT are not working? That's not good! Can you please create a dump when trying to read a L file (debug level 4)? I can try to see if there is something obvious about the error code. I only have a PLC/5 to test on, so all that is guess work on my part.

Strings are quite painful. However, I can see what I can do to make the reads easier in the core library. With Control/Compact Logix systems, I just allocate the tag buffer as I am reading in the data. For PCCC-based systems (MicroLogix, SLC, PLC/5), I do not. I will see if there is anything I can do to make that work as well. Then you could read a string in. The problem is when you want to read a string in and then write out a longer string. Then there is no buffer space.

I may need to special case strings. They are not an atomic type like INT and they are not an array and they are not a UDT. And they seem to be quite different on Micro800 PLCs too.

kyle-github commented 4 years ago

This is interesting - it means we will have to have different marshallers for different CPU types.

Thank AB. There are three string formats that I am aware of:

  1. ControlLogix/CompactLogix: 88 bytes with a 4-byte length count and 82 bytes of data and two bytes of padding.
  2. PCCC PLCs: 82 bytes of data and 2-byte count word. Total of 84 bytes. I think. I'll need to double check.
  3. Micro800: one byte count word and up to 255 bytes of data, I think. It really is not clear and I have only had about five minutes of time with one.

AB is NOT a single family. It is at least three. Multiple times I have come close to splitting the code into three completely separate sections for the different PLC types. And there are significant differences between PLC/5, SLC and MicroLogix. The latter two are quite similar but seem to support different maximum packet sizes. But commands for a PLC/5 rarely work for SLC/MicroLogix and vice versa.

timyhac commented 4 years ago

Thanks Kyle!

@IanRobo75 - RSLogix provides the tag size when you browse the controller data types, at least for CompactLogix, I'm not sure how this works for other CPU types (or other versions of RSLogix for that matter). image

@kyle-github - One thing I was thinking about doing was providing some guidance on how to reverse-engineer the binary format of a tag (assuming you already know the tag size). I've ended up using a combination of Rockwell manuals and hex-format viewing to get this working for an array of UDTs with embedded Structures - seems to work OK but it's not straightforward.

IanRobo75 commented 4 years ago

Ye, I’m pretty sure it will work for Logix. Standard CLX (Logix) strings are 88 bytes and you can create your own string types of different lengths as well (not a big requirement for this). SLC/ML addresses are variable length (well at least that how they are presented). MicroLogix example (looks the same for SLC)… [cid:image001.png@01D65F67.57D7F7D0] For the above example I can set up a tag ST102:0 as length 25 and it reads OK. Any more or less length and it doesn’t read (TOO SMALL or TOO BIG error codes). As I said before it’s not a big issue for me as we’ll only probably read Strings from CLX PLCs. Also, we just change L to N in addresses, I: to N1, and o: no N0, before reading/writing, and set the length appropriately. I haven’t time to test too far since completing my project is #1 priority.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Tuesday, July 21, 2020 1:49 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Thanks Kyle!

@IanRobo75https://github.com/IanRobo75 - RSLogix provides the tag size when you browse the controller data types, at least for CompactLogix, I'm not sure how this works for other CPU types (or other versions of RSLogix for that matter). [image]https://user-images.githubusercontent.com/19144307/88003299-de3ede00-cb47-11ea-9de8-99b954eb9673.png

@kyle-githubhttps://github.com/kyle-github - One thing I was thinking about doing was providing some guidance on how to reverse-engineer the binary format of a tag (assuming you already know the tag size). I've ended up using a combination of Rockwell manuals and hex-format viewing to get this working for an array of UDTs with embedded Structures - seems to work OK but it's not straightforward.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661547793, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY566XLDPZSOPENRZH3R4TXXHANCNFSM4PB255VQ.

IanRobo75 commented 4 years ago

By the way. Here’s the actual format of a string as presented in Studio5000…. [cid:image001.png@01D65F6B.0287EC50]

4 bytes for LENgth + 82 bytes for character codes +2 for something else unknown to me.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Tuesday, July 21, 2020 1:49 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Thanks Kyle!

@IanRobo75https://github.com/IanRobo75 - RSLogix provides the tag size when you browse the controller data types, at least for CompactLogix, I'm not sure how this works for other CPU types (or other versions of RSLogix for that matter). [image]https://user-images.githubusercontent.com/19144307/88003299-de3ede00-cb47-11ea-9de8-99b954eb9673.png

@kyle-githubhttps://github.com/kyle-github - One thing I was thinking about doing was providing some guidance on how to reverse-engineer the binary format of a tag (assuming you already know the tag size). I've ended up using a combination of Rockwell manuals and hex-format viewing to get this working for an array of UDTs with embedded Structures - seems to work OK but it's not straightforward.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661547793, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY566XLDPZSOPENRZH3R4TXXHANCNFSM4PB255VQ.

kyle-github commented 4 years ago

@IanRobo75 , for some reason that is not coming through for me.

Strings are clearly a problem. They are a special UDT that is common enough that there should probably be a way to deal with them that is not so painful.

Right now, the only way to deal with them is to allocate the full 82 characters plus space for the length word. But on ControlLogix (and Micro800), we do not actually know that we are dealing with STRING types until we read the tag. At least with PCCC PLCs, you have the data file type, so the tag size could be set initially.

I'll have to think about this a bit.

timyhac commented 4 years ago

The case where String tags are static in size would be relatively easy to handle in the wrapper, the Encoder/Decoder/Marshaller just needs to know which Cpu type its targeting, and change its logic accordingly.

My understanding (based on some tests of string arrays), is that even though the LEN property tells us how many characters are in the string, the size of the entire tag is always 88 bytes, so if LEN was 12, then there would be 12 ASCII characters, and then 70 null characters.

If the actual size of the tag changes depending on the data in it, then that would be tricky... It would have to be two round trips.... Hmmm...

IanRobo75 commented 4 years ago

Probably true about the actual length of a String in a Micrologix/SLC actually being 82 characters (bytes) + 2 bytes for the .LEN in the PLC (not 88, that is Logix only). However I found you can’t always set the libplctag.NET read tag length as 82, I just errors. I had to set the length of the libplctag.NE tag to the actual number of characters in the string (as seen in the LEN property in the PLC) for it not to error. So maybe the wrapper would need 2 trips, one to read LEN (e.g. 12) and then another to read that number of characters and put them in the 82 long string with null padding after that (e.g. from characters 13 to 82). I hope that makes sense.

From: timyhac notifications@github.com Sent: Tuesday, 21 July 2020 8:09 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

The case where String tags are static in size would be relatively easy to handle in the wrapper, the Encoder/Decoder/Marshaller just needs to know which Cpu type its targeting, and change its logic accordingly.

My understanding (based on some tests of string arrays), is that even though the LEN property tells us how many characters are in the string, the size of the entire tag is always 88 bytes, so if LEN was 12, then there would be 12 ASCII characters, and then 70 null characters.

If the actual size of the tag changes depending on the data in it, then that would be tricky... It would have to be two round trips.... Hmmm...

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661705029, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY3GPVY3CHHEZCOKYG3R4VELBANCNFSM4PB255VQ.

kyle-github commented 4 years ago

I seem to remember cases where some PCCC PLCs return just the string data and the length without any padding. Does anyone have a MicroLogix or SLC to test that theory?

If that is true, then the core library needs to have some additions in order to recognize string types and behave correctly. For *Logix PLCs, you get the whole string buffer, so there is always space. But in cases where you do not get the whole buffer the library will need to change behavior because PCCC PLCs do not return a status indicating that there is more data left. You just get what you get in the packet.

kyle-github commented 4 years ago

I definitely want to avoid multiple round trips, so the important check here is to see if anything returns variable length results.

kyle-github commented 4 years ago

This is interesting - it means we will have to have different marshallers for different CPU types.

Thank AB. There are three string formats that I am aware of:

  1. ControlLogix/CompactLogix: 88 bytes with a 4-byte length count and 82 bytes of data and two bytes of padding.
  2. PCCC PLCs: 82 bytes of data and 2-byte count word. Total of 84 bytes. I think. I'll need to double check.
  3. Micro800: one byte count word and up to 255 bytes of data, I think. It really is not clear and I have only had about five minutes of time with one.

AB is NOT a single family. It is at least three. Multiple times I have come close to splitting the code into three completely separate sections for the different PLC types. And there are significant differences between PLC/5, SLC and MicroLogix. The latter two are quite similar but seem to support different maximum packet sizes. But commands for a PLC/5 rarely work for SLC/MicroLogix and vice versa.

IanRobo75 commented 4 years ago

So, I created a project using libplctag.NativeImport and I can read a string from a MicroLogix on problem, element Size 84 (2 + 82), read a UINT for the string size, then read that number of characters. The character are byte-swapped so I deal with that as well. Here’s example results… [cid:image001.png@01D6600F.115F1BF0] [cid:image003.png@01D66010.32F81270] Can’t do that with the normal wrapper.

This nativeimport version is much more usable for us since we in our program define the tag type and size anyway so can just deal with string as I have done in this example.

And here’s the Windows forms code for that: using System; using System.Diagnostics; using System.Windows.Forms; using libplctag.NativeImport;

namespace libplctagTest { public partial class frmMain : Form { public frmMain() { InitializeComponent(); }

    private void btnTest_Click(object sender, EventArgs e)
    {
        //constants
        const int STATUS_OK = 0;
        const int VER_MAJOR = 2;
        const int VER_MINOR = 1;
        const int VER_PATCH = 0;

        int elementCount = 1;
        int elementSize =84;
        string tagname = "ST102:1";

        string path = "protocol=ab_eip" +
            "&gateway=192.168.5.151" +
            "&cpu=MicroLogix" +
            "&elem_size=" + elementSize.ToString() +
            "&elem_count =" + elementCount.ToString() +
            "&name=" + tagname +
            "&debug=1";

        //clear result textbox on form
        tbResult.Clear();

        // check the library version.
        if (plctag.check_lib_version(VER_MAJOR, VER_MINOR, VER_PATCH) != STATUS_OK)
        {
            Debug.Print("Required compatible library version 2.1.0 not available!\n");
            return;
        }

        //create tag
        Int32 tag = plctag.create(path, 5000);

        //check could be created
        if (tag < 0)
        {
            Debug.Print("ERROR " + plctag.decode_error(tag) + " : Could not create tag!\n");
            return;
        }

        //check for error
        if (plctag.status(tag) != STATUS_OK)
        {

            Debug.Print("Error setting up tag internal state.  Error " + plctag.decode_error(tag) + "\n");
            plctag.destroy(tag);
            return;
        }

        int rc = plctag.read(tag, 5000);
        if (rc != STATUS_OK)
        {

            Debug.Print("ErRROR: Unable to read the data! Got error code " + rc.ToString() + " : " + plctag.decode_error(rc) + "\n");
            plctag.destroy(tag);
            return;
        }

        /* print out the data */
        for (int i = 0; i < elementCount; i++)
        {
            //get the string size (from byte 0)
            int iStringSize = plctag.get_int16(tag, (i * elementSize));
            tbResult.Text += "String LEN = " + iStringSize.ToString() + Environment.NewLine;
            tbResult.Text += "--------------------------------------------" + Environment.NewLine;

            string sb = "";
            string charBuffer = "";

            //string result = tagname + ", element " + i.ToString() + "=" + plctag.get_int16(tag, (i * elementSize)) + "\n";
            for (int j = 2; j < iStringSize +2; j++)
            {
                int iresult = plctag.get_uint8(tag, (i * elementSize) + j);
                string result = tagname +
                    ", element " + i.ToString() +
                    ", byte " + j.ToString() +
                    "=" + iresult.ToString() +
                    "\t= " + ((char)iresult).ToString();
                Debug.Print(result+ Environment.NewLine);
                tbResult.Text += result + Environment.NewLine;
                if (iresult == 0) { tbResult.Text += Environment.NewLine; }

                if (j % 2 == 0)
                {
                    //even so buffer character
                    charBuffer = ((char)iresult).ToString();
                }
                else
                {
                    //odd so add new character, then buffered, and clear buffer
                    sb += ((char)iresult).ToString() + charBuffer;
                    charBuffer = "";
                }
            }

            //add any remaining buffer char
            sb += charBuffer;
            tbResult.Text += "--------------------------------------------" + Environment.NewLine;
            tbResult.Text += tagname + " Full String = '" + sb + "'" + Environment.NewLine;
        }

    }
}

}

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: Kyle Hayes notifications@github.com Sent: Wednesday, July 22, 2020 2:39 AM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

I definitely want to avoid multiple round trips, so the important check here is to see if anything returns variable length results.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661901769, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY4RHTAE6A7AJQVGIT3R4WSB5ANCNFSM4PB255VQ.

IanRobo75 commented 4 years ago

ah, libplctag.NativeImport is good for strings but doesn’t let me read L9:5 from a ML (MicroLogix). The normal wrapper let me read is as N9:4 with element size of 4 but I can’t get the native wrapper to read it at all (PLCTAG_ERR_BAD_PARAM).

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: Ian Robinson Sent: Wednesday, July 22, 2020 10:13 AM To: libplctag/libplctag.NET reply@reply.github.com Subject: RE: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

So, I created a project using libplctag.NativeImport and I can read a string from a MicroLogix on problem, element Size 84 (2 + 82), read a UINT for the string size, then read that number of characters. The character are byte-swapped so I deal with that as well. Here’s example results… [cid:image004.png@01D66014.1B63DC30][cid:image005.png@01D66014.1B63DC30] Can’t do that with the normal wrapper.

This nativeimport version is much more usable for us since we in our program define the tag type and size anyway so can just deal with string as I have done in this example.

And here’s the Windows forms code for that:

using System; using System.Diagnostics; using System.Windows.Forms; using libplctag.NativeImport;

namespace libplctagTest { public partial class frmMain : Form { public frmMain() { InitializeComponent(); }

    private void btnTest_Click(object sender, EventArgs e)
    {
        //constants
        const int STATUS_OK = 0;
        const int VER_MAJOR = 2;
        const int VER_MINOR = 1;
        const int VER_PATCH = 0;

        int elementCount = 1;
        int elementSize =84;
        string tagname = "ST102:1";

        string path = "protocol=ab_eip" +
            "&gateway=192.168.5.151" +
            "&cpu=MicroLogix" +
            "&elem_size=" + elementSize.ToString() +
            "&elem_count =" + elementCount.ToString() +
            "&name=" + tagname +
            "&debug=1";

        //clear result textbox on form
        tbResult.Clear();

        // check the library version.
        if (plctag.check_lib_version(VER_MAJOR, VER_MINOR, VER_PATCH) != STATUS_OK)
        {
            Debug.Print("Required compatible library version 2.1.0 not available!\n");
            return;
        }

        //create tag
        Int32 tag = plctag.create(path, 5000);

        //check could be created
        if (tag < 0)
        {
            Debug.Print("ERROR " + plctag.decode_error(tag) + " : Could not create tag!\n");
            return;
        }

        //check for error
        if (plctag.status(tag) != STATUS_OK)
        {

            Debug.Print("Error setting up tag internal state.  Error " + plctag.decode_error(tag) + "\n");
            plctag.destroy(tag);
            return;
        }

        int rc = plctag.read(tag, 5000);
        if (rc != STATUS_OK)
        {

            Debug.Print("ErRROR: Unable to read the data! Got error code " + rc.ToString() + " : " + plctag.decode_error(rc) + "\n");
            plctag.destroy(tag);
            return;
        }

        /* print out the data */
        for (int i = 0; i < elementCount; i++)
        {
            //get the string size (from byte 0)
            int iStringSize = plctag.get_int16(tag, (i * elementSize));
            tbResult.Text += "String LEN = " + iStringSize.ToString() + Environment.NewLine;
            tbResult.Text += "--------------------------------------------" + Environment.NewLine;

            string sb = "";
            string charBuffer = "";

            //string result = tagname + ", element " + i.ToString() + "=" + plctag.get_int16(tag, (i * elementSize)) + "\n";
            for (int j = 2; j < iStringSize +2; j++)
            {
                int iresult = plctag.get_uint8(tag, (i * elementSize) + j);
                string result = tagname +
                    ", element " + i.ToString() +
                    ", byte " + j.ToString() +
                    "=" + iresult.ToString() +
                    "\t= " + ((char)iresult).ToString();
                Debug.Print(result+ Environment.NewLine);
                tbResult.Text += result + Environment.NewLine;
                if (iresult == 0) { tbResult.Text += Environment.NewLine; }

                if (j % 2 == 0)
                {
                    //even so buffer character
                    charBuffer = ((char)iresult).ToString();
                }
                else
                {
                    //odd so add new character, then buffered, and clear buffer
                    sb += ((char)iresult).ToString() + charBuffer;
                    charBuffer = "";
                }
            }

            //add any remaining buffer char
            sb += charBuffer;
            tbResult.Text += "--------------------------------------------" + Environment.NewLine;
            tbResult.Text += tagname + " Full String = '" + sb + "'" + Environment.NewLine;
        }

    }
}

}

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: Kyle Hayes notifications@github.com<mailto:notifications@github.com> Sent: Wednesday, July 22, 2020 2:39 AM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com<mailto:libplctag.NET@noreply.github.com> Cc: IanRobo75 ian@acompleteloss.com<mailto:ian@acompleteloss.com>; Mention mention@noreply.github.com<mailto:mention@noreply.github.com> Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

I definitely want to avoid multiple round trips, so the important check here is to see if anything returns variable length results.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-661901769, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY4RHTAE6A7AJQVGIT3R4WSB5ANCNFSM4PB255VQ.

timyhac commented 4 years ago

Thanks for checking this Ian. Very interesting that the characters are byte swapped!

I have no experience with MicroLogix - are "N" tags 16 bits (element size = 2)?

Update: 16bits not bytes

timyhac commented 4 years ago

@IanRobo75 - please not I've just released a new (still alpha) version of NativeImport. Main difference for you is the names of the methods have changed to 100% reflect the C API. Also included are constants (StatusCodes etc) so you don't have to define these yourself.

kyle-github commented 4 years ago

@IanRobo75, thanks for the checks.

I had a report a while back of byte swapped character pairs in strings but I never was able to replicate it. That says to me that I need to treat strings as a completely different data type in the core library. Note that strings are different across different PLCs.

I had to update some PLC/5 code recently because the words within a REAL were byte swapped.

IanRobo75 commented 4 years ago

Micrologix types just like SLC500 and PLC5, although I think there are no L files in PLC5…

B Bits, but 16-bit signed Integers really (in the PLC you can reference them as individual bits as well as integer/Bit, so B3/16 is also B3:1/0) (element size = 2) N 16-bit signed Integer (element size = 2) L 32-bit signed Integer (element size = 4) F 32-bit Float (IEEE 754 binary 32) (element size = 4) ST 82 char string (+ 2 preceding bytes for Length) (element size = 84) also… A 2 ASCII characters - forget about these T Timer structure - forget about these C Counter structure - forget about these R Control structure - forget about these M Message structure - forget about these PD PID structure - forget about these O & I Special case of N - forget about these.

Logix types are much more standard... BOOL Boolean bit (can also have arrays of in groups of 32 e.g. testBOOL[64]) SINT 8-bit signed integer (can also have up to 3 dimensions of arrays, e.g. testSINT[5,10,15]) INT 16-bit signed integer (can also have up to 3 dimensions of arrays, e.g. testINT[5,10,15]) DINT 32-bit signed integer (can also have up to 3 dimensions of arrays, e.g. testDINT[5,10,15]) LINT 64-bit signed integer (can also have up to 3 dimensions of arrays, e.g. testLINT[5,10,15]) REAL 32-bit real (IEEE 754 binary 32)) (can also have up to 3 dimensions of arrays, e.g. testREAL[5,10,15])also… TIMER COUNTER CONTROL MESSAGE other types & user defined types (structures).

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Wednesday, July 22, 2020 11:11 AM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Thanks for checking this Ian. Very interesting that the characters are byte swapped!

I have no experience with MicroLogix - are "N" tags 16 bytes (element size = 2)?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662152463, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY3LQBSNQBPWTISQT2TR4YOBFANCNFSM4PB255VQ.

IanRobo75 commented 4 years ago

@IanRobo75 - please not I've just released a new (still alpha) version of NativeImport. Main difference for you is the names of the methods have changed to 100% reflect the C API. Also included are constants (StatusCodes etc) so you don't have to define these yourself.

Yep, makes sense, I've updated my ML test example accordingly.

Still can't read L9:5 though (using libplctag), even as N9:5; get PLCTAG_ERR_BAD_PARAM.

Here's the level 4 debug...

2389-06-22 12:11:25.236 thread(1) tag(0) INFO find_tag_create_func:95 Matched protocol=ab_eip 2389-06-22 12:11:25.236 thread(1) tag(0) INFO ab_tag_create:197 Starting. 2389-06-22 12:11:25.236 thread(1) tag(0) INFO rc_alloc_impl:111 Starting, called from ab_tag_create:204 2389-06-22 12:11:25.236 thread(1) tag(0) INFO rc_alloc_impl:130 Done 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL rc_alloc_impl:135 Returning memory pointer 011965B8 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL ab_tag_create:211 tag=011965B8 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL get_plc_type:1695 Found SLC 500 PLC. 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL get_plc_type:1695 Found SLC 500 PLC. 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL session_find_or_create:226 Starting 2389-06-22 12:11:25.236 thread(2) tag(0) INFO tag_tickler_func:187 Starting. 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL session_find_or_create:250 Creating new session. 2389-06-22 12:11:25.236 thread(1) tag(0) INFO session_create_unsafe:432 Starting 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL session_create_unsafe:434 Warning: not using passed port 44818 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL session_create_unsafe:439 Session should not use connected messaging. 2389-06-22 12:11:25.236 thread(1) tag(0) INFO rc_alloc_impl:111 Starting, called from session_create_unsafe:442 2389-06-22 12:11:25.236 thread(1) tag(0) INFO rc_alloc_impl:130 Done 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL rc_alloc_impl:135 Returning memory pointer 090824E0 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL add_session_unsafe:306 Starting 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL add_session_unsafe:316 Done 2389-06-22 12:11:25.236 thread(1) tag(0) INFO session_create_unsafe:537 Done 2389-06-22 12:11:25.236 thread(1) tag(0) INFO session_init:553 Starting. 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL thread_create:612 Starting. 2389-06-22 12:11:25.236 thread(1) tag(0) DETAIL thread_create:646 Done. 2389-06-22 12:11:25.237 thread(1) tag(0) INFO session_init:567 Done. 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL session_find_or_create:296 Done 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL ab_tag_create:293 using session=090824E0 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL ab_tag_create:324 Setting up SLC/MicroLogix tag. 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL slc_encode_tag_name:316 Starting. 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL parse_pccc_logical_address:743 Starting. 2389-06-22 12:11:25.237 thread(1) tag(0) WARN parse_pccc_file_type:906 Bad format or unsupported logical address L9:5! 2389-06-22 12:11:25.237 thread(1) tag(0) DETAIL parse_pccc_file_type:912 Done. 2389-06-22 12:11:25.237 thread(1) tag(0) WARN parse_pccc_logical_address:747 Unable to parse PCCC-style tag for data-table type! Error PLCTAG_ERR_BAD_PARAM! 2389-06-22 12:11:25.238 thread(3) tag(0) INFO session_handler:925 Starting thread for session 090824E0 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL parse_pccc_logical_address:767 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) WARN slc_encode_tag_name:327 Unable to parse SLC logical addresss! 2389-06-22 12:11:25.238 thread(3) tag(0) DETAIL session_handler:944 in SESSION_OPEN_SOCKET state. 2389-06-22 12:11:25.238 thread(1) tag(0) WARN check_tag_name:1758 parse of SLC-style tag name L9:5 failed! 2389-06-22 12:11:25.238 thread(3) tag(0) INFO session_open_socket:583 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) INFO ab_tag_create:437 Bad tag name! 2389-06-22 12:11:25.238 thread(3) tag(0) DETAIL socket_create:835 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) WARN plc_tag_create:567 Error PLCTAG_ERR_BAD_PARAM while trying to create tag! 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL rc_dec_impl:242 Calling cleanup functions due to call at plc_tag_create:568 for 011965B8. 2389-06-22 12:11:25.238 thread(1) tag(0) INFO refcount_cleanup:256 Starting 2389-06-22 12:11:25.238 thread(1) tag(0) INFO ab_tag_destroy:753 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL ab_tag_destroy:765 Getting ready to release tag session 090824E0 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL ab_tag_destroy:767 Removing tag from session. 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL rc_dec_impl:242 Calling cleanup functions due to call at ab_tag_destroy:768 for 090824E0. 2389-06-22 12:11:25.238 thread(1) tag(0) INFO refcount_cleanup:256 Starting 2389-06-22 12:11:25.238 thread(1) tag(0) INFO session_destroy:722 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL remove_session:367 Starting. 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL remove_session_unsafe:343 Starting 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL remove_session_unsafe:358 Done 2389-06-22 12:11:25.238 thread(1) tag(0) DETAIL remove_session:375 Done. 2389-06-22 12:11:25.238 thread(1) tag(0) INFO session_destroy:733 Session sent 0 packets. 2389-06-22 12:11:25.240 thread(3) tag(0) DETAIL socket_create:854 Done. 2389-06-22 12:11:25.240 thread(3) tag(0) DETAIL socket_connect_tcp:874 Starting. 2389-06-22 12:11:25.249 thread(3) tag(0) DETAIL socket_connect_tcp:923 Found numeric IP address: 192.168.5.151 2389-06-22 12:11:25.250 thread(3) tag(0) DETAIL socket_connect_tcp:1014 Done. 2389-06-22 12:11:25.250 thread(3) tag(0) INFO session_open_socket:600 Done. 2389-06-22 12:11:25.250 thread(3) tag(0) DETAIL session_handler:1137 Critical block. 2389-06-22 12:11:25.256 thread(1) tag(0) INFO session_close_socket:703 Starting. 2389-06-22 12:11:25.259 thread(1) tag(0) INFO session_close_socket:711 Done. 2389-06-22 12:11:25.259 thread(1) tag(0) INFO session_destroy:806 Done. 2389-06-22 12:11:25.259 thread(1) tag(0) INFO refcount_cleanup:268 Done. 2389-06-22 12:11:25.259 thread(1) tag(0) INFO ab_tag_destroy:789 Finished releasing all tag resources. 2389-06-22 12:11:25.259 thread(1) tag(0) INFO ab_tag_destroy:791 done 2389-06-22 12:11:25.259 thread(1) tag(0) INFO refcount_cleanup:268 Done.

timyhac commented 4 years ago

Interesting - what is the full attribute string for this tag? I don't think I can help but it might clarify.

IanRobo75 commented 4 years ago

Here are my results reading different MicroLogix data types with libplctag.NativeImport ...

How to read the data successfully... O:0.0 - Read as O0:0 as element length 2 O:0.1 - Read as O0:0 as element length 4 and use bytes 2 & 3 O:1.1 - Read as O0:1 as element length 2 O:1.2 - Read as O0:1 as element length 4 and use bytes 2 & 3 I:0 - Read as I1:0 S:4 - Read as S2:4 B3:0 - Read as B3:0 [same] T4:0.PRE - Read as T4:0.PRE [same] C5:0.PRE - Read as C5:0.PRE [same] N7:0 - Read as N7:0 [same] L9:5 - !!! can't read in any form !!! ST102:0 - Read as ST102:0 [same] (then decode bytes 0 & 1 as length, and that length of characters from byte 2 onwards)

Note all the working ones are 16-bit integers [element size 2] + the string [element size 84].

kyle-github commented 4 years ago

Well that points to the problem!

2389-06-22 12:11:25.237 thread(1) tag(0) WARN parse_pccc_file_type:906 Bad format or unsupported logical address L9:5!

Looks like I am not handling the L type. And it looks like I do not have the data type byte I need for it. My DF1 docs are so old that I do not see a 32-bit integer type in them. I will need to hunt around to see if there is an updated version of the PCCC protocol docs.

I am using PLC/5-specific commands to read my PLC/5 and with those (but not the commands I was using!) I see the byte swapped characters as well. But the count/LEN field is little-endian. Oh how I love AB.

IanRobo75 commented 4 years ago

from here... https://www.sciencedirect.com/science/article/pii/S1742287617301998

looks like the L file is file type 0x91 in the PCCC protocol...

Test Cases | Classified File-type

Data Files/New/select Type:Binary | – | New file B9 | 0x85 Data Files/New/select Type:Integer | – | New file N10 | 0x89 Data Files/New/select Type:Long | – | New file L11 | 0x91 Data Files/New/select Type:Message | – | New file MSG12 | 0x92 Data Files/New/select Type:PID | – | New file PI13 | 0x93

timyhac commented 4 years ago

@kyle-github - if you'd prefer to handle strings in the C library that is Ok, but it is relatively easy to develop marshalling logic based on Cpu type - although it would mean that all of the wrappers would need to implement this separately.

IanRobo75 commented 4 years ago

would be better if the wrapper handled it of course. The wrapper could also change O to O0, I to I1, and S to S2 in the addresses (e.g. O:0 become O0:0).

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Wednesday, July 22, 2020 1:41 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

@kyle-githubhttps://github.com/kyle-github - if you'd prefer to handle strings in the C library that is Ok, but it is relatively easy to develop marshalling logic based on Cpu type - although it would mean that all of the wrappers would need to implement this separately.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662192733, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY6735KLGRC7U5CRSY3R4Y7SLANCNFSM4PB255VQ.

kyle-github commented 4 years ago

@IanRobo75, thanks.! Where did you get that table? I was able to fill in three gaps from it. Here is what I have now:

        case PCCC_FILE_ASCII: return 0x8e; break;
        case PCCC_FILE_BIT: return 0x85; break;
        case PCCC_FILE_BLOCK_TRANSFER: break;
        case PCCC_FILE_COUNTER: return 0x87; break;
        case PCCC_FILE_BCD: return 0x8f; break;
        case PCCC_FILE_FLOAT: return 0x8a; break;
        case PCCC_FILE_INPUT: return 0x8c; break;
        case PCCC_FILE_LONG_INT: return 0x91; break;
        case PCCC_FILE_MESSAGE: return 0x92; break;
        case PCCC_FILE_INT: return 0x89; break;
        case PCCC_FILE_OUTPUT: return 0x8b; break;
        case PCCC_FILE_PID: return 0x93; break;
        case PCCC_FILE_CONTROL: return 0x88; break;
        case PCCC_FILE_STATUS: return 0x84; break;
        case PCCC_FILE_SFC: break;
        case PCCC_FILE_STRING: return 0x8d; break;
        case PCCC_FILE_TIMER: return 0x86; break;

Any idea on block transfer or SFC?

I have a proposed fix in the fix_pccc_long_int branch. It would be great if you could give it a try.

kyle-github commented 4 years ago

@timyhac, I would prefer to tackle strings in the C library. They are a fundamental type and not having support in the core library would mean that support would differ based on the wrappers. While there will be varying degrees of ease of use due to the wrappers, I do want to make sure that all wrappers can support the same common base functionality.

Unlike UDTs, strings are a known (if somewhat annoying) quantity.

There are things that are going to be easier to do in the library, such as handling string lengths. For instance, suppose you read a string from a ControlLogix. You get all 88 bytes all the time. IIRC, on some of the PCCC PLCs, you only get as many bytes as the count and the valid bytes of the string. I think that Micro800 may play games there too. Then there is the problem with the byte swapping. Hiding that from the application would help a lot. Yes, it can easily be solved in the application, but then that is code that every single application or wrapper will need to write. Might as well get it right once in the core library.

timyhac commented 4 years ago

Sounds good @kyle-github

kyle-github commented 4 years ago

I created two new issues in the core library to track these changes:

#163 - Support Long Int on PCCC PLCs. #162 - Support strings in the core library.

The string issue is a tricky one. In order to make this low-friction for users it needs to use the string data type from the application. C strings are relatively well supported by most languages with C interop. At least as parameters. The initial idea I have is two new API functions, a getter and a setter that handle C strings directly.

One huge decision to make here is how to handle the memory involved. None of the PLC string types map well to C strings. Thus, I might need to allocate additional memory in which to populate the return string of the getter. If I have to allocate additional memory, then somehow it needs to be released. I can do that with additional trickery in the library, but that is not ideal.

Alternatively, I can translate the data in situ as all of the string types that I know of use more (or the same) space than an equivalent length C string. So I could translate it in place in the internal tag buffer. Then I could overload the plc_tag_get_size() call or something to return the string length. That does not sound like a great level of abstraction.

I would appreciate it if all of you would weigh in on the issue itself in the core library issues. I at least want to explore the possibility of adding API calls to the library to support this. Perhaps that is the wrong thing to do, but I want to make sure that if we decide not to do that, that there are well understood reasons why it is not a good idea.

IanRobo75 commented 4 years ago

For the wrapper, libplctag, I believe this section of the C library is failing for strings. Assumedly data_end - data is not the 84 bytes I asked for.

eip_slc_pccc.c

    /* did we get the right amount of data? */
    if((data_end - data) != tag->size) {
        if((int)(data_end - data) > tag->size) {
            pdebug(DEBUG_WARN,"Too much data received!  Expected %d bytes but got %d bytes!", tag->size, (int)(data_end - data));
            rc = PLCTAG_ERR_TOO_LARGE;
        } else {
            pdebug(DEBUG_WARN,"Too little data received!  Expected %d bytes but got %d bytes!", tag->size, (int)(data_end - data));
            rc = PLCTAG_ERR_TOO_SMALL;
        }
        break;
    }

When using the libplctag.NativeImport it doesn't go wrong for a reason that's above my level of understanding.

I'm assuming selection of Micrologix plc type means using the above eip_slc file (no real difference between an SLC and a ML).

kyle-github commented 4 years ago

@IanRobo75, string size is PLC-dependent. From the comments made above, it sounded like the wrapper is using a single value of 88. So, it will set the tag size to that, which will then fail the main if check.

This check against the size is something that is not needed when talking with a Control/CompactLogix PLC. In that protocol, there is a status indicator that tells you whether you have received all the data the PLC will send or not. No such thing in PCCC.

kyle-github commented 4 years ago

Oops, and yes, right now the SLC and MicroLogix code are all the same. At least according to the DF1 docs I have, they use the same protocol commands.

timyhac commented 4 years ago

Yes the wrapper has 88 hardcoded against the STRING DataType.

kyle-github commented 4 years ago

I updated the core issue for string support. It is a little lower level than I wanted, but at the same time does abstract away the PLC-specific byte ordering and detailed handling:

int plc_tag_get_string_length(int32_t tag_id, int string_start_offset);
int plc_tag_set_string_length(int32_t tag_id, int string_start_offset, int string_len);
int plc_tag_get_string_char(int32_t tag_id, int string_start_offset, int char_index);
int plc_tag_set_string_char(int32_t tag_id, int string_start_offset, int char_index, int char_val);

This allows the core library to continue to access the tag data as the raw bytes from the PLC. If you want to read a string, you figure out the offset where your string field starts and then call plc_tag_get_string_length(). Then you call plc_tag_get_string_char() for each character with the same offset and an index for each character within the string. The library will handle the real offset calculation based on the PLC and string type.

If you want to write a string, you write the length with plc_tag_set_string_length() first and then successive calls to plc_tag_set_string_char() out to the length of the string.

While this is definitely not as ergonomic as handling C strings directly, it appears to be possible to support counted and non-counted strings and varying byte order and count word sizes transparently to the application or wrapper.

PLCs that use variable length strings are still going to be interesting, but at least there is a solid hook for handling them on a per-PLC basis with this API.

All wrappers should be able to use this API regardless of PLC type. That said, there are clear limits:

  1. As mentioned, variable length strings get real interesting.
  2. Arrays of variable length strings are even more interesting.
  3. The int value returned will be 0-255 for the byte value and negative for an error. No wchar_t. But at least UTF-8 is supported.
  4. A variable length string inside a UDT is probably going to stay in the category of unsupported for a long time. Note that these exist: the tag listing raw data contains exactly this.

Thoughts? It is not as ergonomic, but it removes most, perhaps all, of the PLC-specific code in the wrappers.

IanRobo75 commented 4 years ago

I like it

IanRobo75 commented 4 years ago

is this now in either C# wrapper? I'm a plc guy who knows some c#, not C.

i'll try tomorrow morning (NZ time).

Sent from my Samsung Galaxy smartphone.

-------- Original message -------- From: Kyle Hayes notifications@github.com Date: 22/07/20 3:13 PM (GMT+12:00) To: "libplctag/libplctag.NET" libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com, Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

@IanRobo75https://github.com/IanRobo75, thanks.! Where did you get that table? I was able to fill in three gaps from it. Here is what I have now:

    case PCCC_FILE_ASCII: return 0x8e; break;
    case PCCC_FILE_BIT: return 0x85; break;
    case PCCC_FILE_BLOCK_TRANSFER: break;
    case PCCC_FILE_COUNTER: return 0x87; break;
    case PCCC_FILE_BCD: return 0x8f; break;
    case PCCC_FILE_FLOAT: return 0x8a; break;
    case PCCC_FILE_INPUT: return 0x8c; break;
    case PCCC_FILE_LONG_INT: return 0x91; break;
    case PCCC_FILE_MESSAGE: return 0x92; break;
    case PCCC_FILE_INT: return 0x89; break;
    case PCCC_FILE_OUTPUT: return 0x8b; break;
    case PCCC_FILE_PID: return 0x93; break;
    case PCCC_FILE_CONTROL: return 0x88; break;
    case PCCC_FILE_STATUS: return 0x84; break;
    case PCCC_FILE_SFC: break;
    case PCCC_FILE_STRING: return 0x8d; break;
    case PCCC_FILE_TIMER: return 0x86; break;

Any idea on block transfer or SFC?

I have a proposed fix in the fix_pccc_long_int branch. It would be great if you could give it a try.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662216731, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY5KPBDBTQDYHGEO7TDR4ZKMTANCNFSM4PB255VQ.

timyhac commented 4 years ago

Hi @IanRobo75 - It is not. You can follow the discussion on Strings here https://github.com/libplctag/libplctag/issues/162

Kyle has a proposed change for the Integer problem. To use this you'll need to compile the https://github.com/libplctag/libplctag/tree/Fix_pccc_long_int branch and then replace the plctag.dll in your application folder.

IanRobo75 commented 4 years ago

I don’t know how to complie the files.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Thursday, July 23, 2020 9:44 AM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Hi @IanRobo75https://github.com/IanRobo75 - It is not. You can follow the discussion on Strings here libplctag/libplctag#162https://github.com/libplctag/libplctag/issues/162

Kyle has a proposed change for the Integer problem. To use this you'll need to compile the https://github.com/libplctag/libplctag/tree/Fix_pccc_long_int branch and then replace the plctag.dll in your application folder.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662712884, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY2SVVJVQPSF3OBV2ELR45MRZANCNFSM4PB255VQ.

kyle-github commented 4 years ago

I built and attached the Windows ZIP files with the core DLL in them here. Let me know if you need the other ones!

libplctag_2.1.10_windows_x64.zip libplctag_2.1.10_windows_x86.zip

IanRobo75 commented 4 years ago

OK, dropped the new DLL in my c# project but nothing works and I get the exception….

System.BadImageFormatException HResult=0x8007000B Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) Source=libplctag.NativeImport StackTrace: at libplctag.NativeImport.plctag.destroy(Int32 tag) at libplctag.Tag.Dispose() at libplctag.Tag.Finalize()

I guess you are thinking that I can test the DLL directly in C, which I’m not capable of doing.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: Kyle Hayes notifications@github.com Sent: Thursday, July 23, 2020 12:35 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

I built and attached the Windows ZIP files with the core DLL in them here. Let me know if you need the other ones!

libplctag_2.1.10_windows_x64.ziphttps://github.com/libplctag/libplctag.NET/files/4963334/libplctag_2.1.10_windows_x64.zip libplctag_2.1.10_windows_x86.ziphttps://github.com/libplctag/libplctag.NET/files/4963335/libplctag_2.1.10_windows_x86.zip

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662765015, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY3GGVTM7JD4HVOKLQDR46AUZANCNFSM4PB255VQ.

timyhac commented 4 years ago

Hi @IanRobo75 ,

It is this dll that you need to replace (or insert if you are running it for the first time): image

If there is no file called "plctag.dll" (On Windows), then NativeImport will extract one from itself and desposit it in the filesystem.

IanRobo75 commented 4 years ago

yep, that is exactly what I did, didn’t work.

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Thursday, July 23, 2020 1:37 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

Hi @IanRobo75https://github.com/IanRobo75 ,

It is this dll that you need to replace (or insert if you are running it for the first time): [image]https://user-images.githubusercontent.com/19144307/88244658-ceee9a80-ccd7-11ea-8e53-007800a51553.png

If there is no file called "plctag.dll" (On Windows), then NativeImport will extract one from itself and desposit it in the filesystem.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662779278, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RY6XV2XPEOHNYEZ5XOTR46H3RANCNFSM4PB255VQ.

timyhac commented 4 years ago

I am able to reproduce that error if I use the x86 dll while running on an x64 machine.

I don't have an x86 machine to try the x86 dll on (if this is relevant to you).

IanRobo75 commented 4 years ago

Nope, I extracted the x64 and plctag.dll I’m running Win10-64. I tried it again to be sure.

[cid:image002.png@01D660F9.0CC04A20]

Also using libplctag 0.0.27-alpha09 & libplctag.NativeImport 0.0.7-alpha (0.0.8 has an issue: Method not found: 'Int32 libplctag.NativeImport.plctag.destroy(Int32)'.)

Cheers, Ian Ian Robinson Machine Safety & Automation Engineer [swarmIQ_colour 20%]

From: timyhac notifications@github.com Sent: Thursday, July 23, 2020 1:42 PM To: libplctag/libplctag.NET libplctag.NET@noreply.github.com Cc: IanRobo75 ian@acompleteloss.com; Mention mention@noreply.github.com Subject: Re: [libplctag/libplctag.NET] SLC Strings - PLCTAG_ERR_TOO_SMALL (#58)

I am able to reproduce that error if I use the x86 dll while running on an x64 machine.

I don't have an x86 machine to try the x86 dll on (if this is relevant to you).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/libplctag/libplctag.NET/issues/58#issuecomment-662780347, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIY6RYYEKBNCJ2C2G4YUGB3R46IOPANCNFSM4PB255VQ.

kyle-github commented 4 years ago

Do you need the .pdb file too? Not a Windows programmer, nor do I play one on TV.