eclipse-kura / kura

Eclipse Kura™ is a versatile framework to supercharge your edge devices, streamlining the process of configuring your gateway, connecting sensors, and IoT devices to seamlessly collect, process, and send data to the cloud.
https://eclipse.dev/kura/
Eclipse Public License 2.0
502 stars 309 forks source link

Moka7 library does not provide GetPlcDateTime result #4285

Closed BRoessl closed 1 year ago

BRoessl commented 1 year ago

Describe the bug due to actual two bugs, it is not possible to get plc date time using Moka7.S7Client#GetPlcDateTime

Bug#1

the date result parameter is passed by reference and not mutated, but the reference is altered. the method caller passing the value is not able to get the object created in line 1001 and will hold the reference to the old object. https://github.com/eclipse/kura/blob/0d50f11782caf39c01249ea4ed4535323cb2762c/target-platform/org.moka7/src/main/java/Moka7/S7Client.java#L988-L1011 you can actually mutate the passed-by-reference Date object using setTime() but in general the Moka7 API is a little bit strange because it is coded as in C++.

Bug#2

S7Client#GetPlcDateTime uses internally S7#GetDateAt, which is buggy as well, e.g. the year is decoded in byte 0 and byte 1, following byte offsets are all wrong: https://github.com/eclipse/kura/blob/0d50f11782caf39c01249ea4ed4535323cb2762c/target-platform/org.moka7/src/main/java/Moka7/S7.java#L178-L198 here is a possible fix, but using LocalDateTime (to avoid bad Date API):

    public static LocalDateTime getDateAt(byte[] buffer, int position) {
        int year = S7.BCDtoByte(buffer[position]);
        year = year * 100 + S7.BCDtoByte(buffer[position + 1]);
        int month = S7.BCDtoByte(buffer[position + 2]);
        int day = S7.BCDtoByte(buffer[position + 3]);
        int hour = S7.BCDtoByte(buffer[position + 4]);
        int min = S7.BCDtoByte(buffer[position + 5]);
        int sec = S7.BCDtoByte(buffer[position + 6]);
        int millis = S7.BCDtoByte(buffer[position + 7]);
        millis = millis * 10 + S7.BCDtoByte(buffer[position + 8]) / 10;
        return LocalDateTime.of(year, month, day, hour, min, sec, millis * 1_000_000);
    }

S7 Timestamp encoding is a little bit strange (Hex 20 == Decimal 20), i added a wireshark screenshot which should help to understand.

To Reproduce Older S7 Type can provide date time:

  1. start S7 server (snap7 demo or a real device older(!) than S7 type 1200
  2. connect moka7 client and call GetPlcDateTime
        Date date = new Date(0L);
        int getPlcDateTime = moka7.GetPlcDateTime(date);
        assertEquals(0, getPlcDateTime);
        assertNotEquals(new Date(0L), date);
  3. assertEquals(0, getPlcDateTime); validates that the client has received the S7 Timestamp, but assertNotEquals(new Date(0L), date); will fail and validate that the date has not been updated.

Expected behavior S7Client#GetPlcDateTime works as expected and also S7#GetPlcDateTime has been fixed

Screenshots S7 Timestamp Encoding S7 Timestamp

Target Environment (please complete the following information):

Additional context I am using Moka7 using maven dependency

<dependency>
    <groupId>org.eclipse.kura</groupId>
    <artifactId>org.moka7</artifactId>
    <version>1.1.1</version>
</dependency>
MMaiero commented 1 year ago

@nicolatimeus Can you please have a look? Thanks

nicolatimeus commented 1 year ago

Hi, at the moment the Moka7 source code is in our repository has the only purpose of rewrapping Moka7 1.0.2 as an OSGi bundle for easier integration with Kura. Have you already tried to report the this issue to the Moka7 maintainer?

BRoessl commented 1 year ago

No, since I am using Moka7 via your provided maven artifact. Not sure what the "single source of truth" is regarding this library 😕

nicolatimeus commented 1 year ago

At the moment we are not planning to maintain a custom version of Moka7, so the source of truth is still https://sourceforge.net/projects/snap7/, probably we should make a clear statement about this.

devaskim commented 7 months ago

@nicolatimeus @MMaiero Could you recommend any S7 simulator (application)? I need to test my app based on Moka 7