Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tag string writing #18

Open
InofensivoJimmy opened this issue Dec 31, 2021 · 14 comments
Open

Tag string writing #18

InofensivoJimmy opened this issue Dec 31, 2021 · 14 comments
Labels
question Further information is requested

Comments

@InofensivoJimmy
Copy link

I use the libplctrag4j library. I would like to know the correct way to write on a tag of type string, because sometimes the result is not the desired one

is this correct?
tag4.SetString(0,"value")
tag4.Write(TIMEOUT)

@kyle-github kyle-github added the question Further information is requested label Dec 31, 2021
@kyle-github
Copy link
Member

The method names in Java are setString() and write().

If you are using standard string types, this should work. It is tested and works with Control/CompactLogix, PLC-5 and Micrologix PLCs.

Can you please give more information about what happens when this does not work for you?

@InofensivoJimmy
Copy link
Author

this event is executed by pressing a button.

Private Sub Button1_Click

tag4.SetString(0,TextField_STRING.Text)
tag4.Write(0)
Log(TextField_STRING.Text)


TextField_STRING.Text = ""

End Sub

when pressing the button I write in tag4 the value of an editext. and clean the editext to enter new text.
sometimes the tag4 variable receives the correct value in studio 5000, and other times extra characters are added to the value.
I do the tests with compact logig 5380.
the tag reading if you do it correctly. I have also tried to read and write booleans, integers, reals, all perfect.

@kyle-github
Copy link
Member

Can you please capture debugging output and attach that to this issue? You can use tag.setDebugLevel(Tag.PLCTAG_DEBUG_DETAIL) to set the debug level. This will output a lot of information on stdout. If you are using Windows or a Unix-like system, you can use

program.exe > log.txt 2>&1

That will redirect all the output to the text file log.txt. Please attach that to the issue.

There may be extra characters in the buffer, but the length field should be correct. Is the string of the standard system type STRING?

@InofensivoJimmy
Copy link
Author

log.txt

@InofensivoJimmy
Copy link
Author

This is what you need?
I try to write the variable multiple times.
Some go well, some go bad. I also log the value of my variable every time I try to write it.

@kyle-github
Copy link
Member

Thanks, I will look at this today.

@kyle-github
Copy link
Member

Sorry, work has been busy.

I see that you are using the previous release, 2.3.4. That is almost a year old. Can you please update to the newest version? It uses version 2.4.9 of the C DLL.

I see some strange values being written to the PLC:

06 00 00 00  <-- string length is 6 bytes
52 41 46 41 ff 01  <-- string data, the last two bytes are not valid ASCII

00 00 <--- this and the rest are zero padding.
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00

The string you are sending to the C DLL is not valid ASCII. It is not valid UTF-8 encoded UNICODE. Please check the value you are setting the string to. It is not valid ASCII or UTF-8 data.

@kyle-github
Copy link
Member

Did you find out what is causing your string data to be damaged?

@InofensivoJimmy
Copy link
Author

No, I did the same test with the JAVA wrapper in itenjiJ and the same problem, I don't know what can happen. Is there any way to force the LEN value of the string after writing it?

@kyle-github
Copy link
Member

You can force the length after calling setString(), but the fact that the data shows the string to be the wrong length means that you are passing an incorrect string to the library. Are you using a String or a byte[]?

@InofensivoJimmy
Copy link
Author

I am using a string, how can I force the length?

@InofensivoJimmy
Copy link
Author

This is the code in the itenlliJ project, with the libplctag4J container, version 2-4-12. I work with compactLogix 5380. It has the same problem when writing the tag string:

package com.company;

import io.github.libplctag.Tag;

import java.util.Scanner;

public class Main {

static final int TIMEOUT = 5000;
static int lastState = -1;

public static void main(String[] args) {
    int rc = Tag.PLCTAG_STATUS_OK;

    // check the library version.
    if(!Tag.checkLibraryVersion(2, 3, 4)) {
        System.err.println("This version of the library does not support the required version of 2.3.4!");
        System.exit(1);
    }

    // set the debug level.
    Tag.setDebugLevel(Tag.PLCTAG_DEBUG_NONE);

    // get the library version
    int version_major = Tag.getLibraryIntAttribute("version_major", 0);
    int version_minor = Tag.getLibraryIntAttribute("version_minor", 0);
    int version_patch = Tag.getLibraryIntAttribute("version_patch", 0);

    System.err.println("Using library version " + version_major + "." + version_minor + "." + version_patch + ".");

    Tag PRUEBA_TAG4 = new Tag("protocol=ab-eip&gateway=192.168.18.100&path=1,0&plc=ControlLogix&elem_count=1&name=PRUEBA_TAG4", TIMEOUT);
    // get the string
    String str = PRUEBA_TAG4.getString(0);
    if(str == null) {
        rc = PRUEBA_TAG4.getStatus();
        System.err.println("Unable to read the string, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);
    }

    System.err.println("Value is: \"" + str + "\".");


    // set a String value
    Scanner myObj = new Scanner(System.in);  // Create a Scanner object
    System.out.println("Enter value");
    String inputValue = myObj.nextLine();  // Read user input

    PRUEBA_TAG4 = new Tag("protocol=ab-eip&gateway=192.168.18.100&path=1,0&plc=ControlLogix&elem_count=1&name=PRUEBA_TAG4", TIMEOUT);
    PRUEBA_TAG4.setString(0, inputValue.trim());
    PRUEBA_TAG4.write(0);
    rc = PRUEBA_TAG4.getStatus();
    if(rc != Tag.PLCTAG_STATUS_OK) {
        System.err.println("Unable to write the tag, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);

// PRUEBA_TAG4.
}

    // get the string
    String str1 = PRUEBA_TAG4.getString(0);
    if(str == null) {
        rc = PRUEBA_TAG4.getStatus();
        System.err.println("Unable to read the string, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);
    }

    System.err.println("Value is: \"" + str1 + "\".");

    // done with the tag
    PRUEBA_TAG4.close();


} //end of Main method

}

@kyle-github
Copy link
Member

There are a few things that are incorrect in this code.

First, when you read or write a tag, you need to wait for the operation to be sent to the PLC and the response to come back to the PC. You can do that in two ways:

  1. Use the synchronous mode by passing read()/write() a non-zero timeout value. I.e. tag.write(1000) or tag.read(1000). That will wait for up to 1000 milliseconds for the PLC to return a response. If the PLC returns a response before the 1000ms passes, then the read or write returns. If the PLC does not return a response before the 1000ms passes, then the read or write returns with an error of PLCTAG_ERR_TIMEOUT.
  2. Use asynchronous mode by passing a zero timeout, i.e. tag.write(0), and then waiting for the response in your code. You do that by looping until the status changes.
// start the write operation
int status = tag.write(0);

// now wait in a loop for operation to finish.
while(status == tag.PLCTAG_STATUS_PENDING) {
   Thread.sleep(20); // sleep 20 milliseconds
   status = tag.getStatus();
}

// below here you should check the status to make sure the operation succeeded.

Second, you need to explicitly read and write tag values. You are calling write(), but I do not see calls to read() after you change a value. Calling read() sends a request to the PLC to get the value of the tag. When the PLC responds, that value is loaded into the tag's internal buffer in memory in the PC. When you call write(), the value in the tag's memory in the PC is sent to the PLC.

To help debugging, please output the length of the string as well as the value.

@InofensivoJimmy
Copy link
Author

This is better?:

`package com.company;

import io.github.libplctag.Tag;

import java.util.Scanner;

public class Main {

static final int TIMEOUT = 5000;
static int lastState = -1;

public static void main(String[] args) {
    int rc = Tag.PLCTAG_STATUS_OK;

    // check the library version.
    if(!Tag.checkLibraryVersion(2, 3, 4)) {
        System.err.println("This version of the library does not support the required version of 2.3.4!");
        System.exit(1);
    }

    // set the debug level.
    Tag.setDebugLevel(Tag.PLCTAG_DEBUG_NONE);

    // get the library version
    int version_major = Tag.getLibraryIntAttribute("version_major", 0);
    int version_minor = Tag.getLibraryIntAttribute("version_minor", 0);
    int version_patch = Tag.getLibraryIntAttribute("version_patch", 0);

    System.err.println("Using library version " + version_major + "." + version_minor + "." + version_patch + ".");

    Tag PRUEBA_TAG4 = new Tag("protocol=ab-eip&gateway=192.168.18.100&path=1,0&plc=ControlLogix&elem_count=1&name=PRUEBA_TAG4", TIMEOUT);
    // get the string
    PRUEBA_TAG4.read(1000);
    String str = PRUEBA_TAG4.getString(0);
    if(str == null) {
        rc = PRUEBA_TAG4.getStatus();
        System.err.println("Unable to read the string, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);
    }

    System.out.println("EL VALOR ES:" +   str);


    // set a String value
    Scanner myObj = new Scanner(System.in);  // Create a Scanner object
    System.out.println("Enter value");
    String inputValue = myObj.nextLine();  // Read user input

    PRUEBA_TAG4 = new Tag("protocol=ab-eip&gateway=192.168.18.100&path=1,0&plc=ControlLogix&elem_count=1&name=PRUEBA_TAG4", TIMEOUT);
    PRUEBA_TAG4.setString(0, inputValue.trim());
    PRUEBA_TAG4.write(1000);
    rc = PRUEBA_TAG4.getStatus();
    if(rc != Tag.PLCTAG_STATUS_OK) {
        System.err.println("Unable to write the tag, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);

// PRUEBA_TAG4.
}

    // get the string
    PRUEBA_TAG4.read(1000);
    String str1 = PRUEBA_TAG4.getString(0);
    System.out.println("EL VALOR ES:" +   str1);
    if(str1 == null) {
        rc = PRUEBA_TAG4.getStatus();
        System.err.println("Unable to read the string, got error " + Tag.decodeError(rc) + "!");
        PRUEBA_TAG4.close();
        System.exit(1);
    }

    //System.err.println("Value is: \"" + str1 + "\".");

    // done with the tag
    PRUEBA_TAG4.close();


} //end of Main method

}`

This is my Main:

C:\Java\jdk-11.0.1\jdk-11.0.1\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=52168:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\rafab\IdeaProjects\PLCDemo\out\production\PLCDemo;C:\Users\rafab\Downloads\libplctag4j-0.9.17-2.4.12\libplctag4j-0.9.17-2.4.12.jar com.company.Main
abr. 12, 2022 4:10:25 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd for /com/sun/jna/win32-x86-64/jnidispatch.dll
abr. 12, 2022 4:10:25 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Found library resource at jar:file:/C:/Users/rafab/Downloads/libplctag4j-0.9.17-2.4.12/libplctag4j-0.9.17-2.4.12.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Users\rafab\AppData\Local\Temp\jna-108272248\jna6861948775390463864.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Looking for library 'plctag'
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Adding paths from jna.library.path: null
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Trying plctag.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Loading failed with message: No se puede encontrar el módulo especificado.

abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Adding system paths: []
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Trying plctag.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Loading failed with message: No se puede encontrar el módulo especificado.

abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Looking for lib- prefix
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Trying libplctag.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Loading failed with message: No se puede encontrar el módulo especificado.

abr. 12, 2022 4:10:26 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd for plctag
abr. 12, 2022 4:10:26 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Found library resource at jar:file:/C:/Users/rafab/Downloads/libplctag4j-0.9.17-2.4.12/libplctag4j-0.9.17-2.4.12.jar!/win32-x86-64/plctag.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Users\rafab\AppData\Local\Temp\jna-108272248\jna15926548935992292880.dll
abr. 12, 2022 4:10:26 A. M. com.sun.jna.NativeLibrary loadLibrary
INFO: Found library 'plctag' at C:\Users\rafab\AppData\Local\Temp\jna-108272248\jna15926548935992292880.dll
Using library version 2.4.12.
EL VALOR ES: RAFA
Enter value
RAFAEL
EL VALOR ES: RAFAEL�

Process finished with exit code 0

Where I read the value, write it and read it again.
I write RAFAEL and some extra characters are added. how does it happen with the B4X wrapper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants