feat(plc4j/slmp): add read-only SLMP (MELSEC 3E) driver#2640
Open
LivingLikeKrillin wants to merge 16 commits into
Open
feat(plc4j/slmp): add read-only SLMP (MELSEC 3E) driver#2640LivingLikeKrillin wants to merge 16 commits into
LivingLikeKrillin wants to merge 16 commits into
Conversation
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Add SlmpParserSerializerTest (extends ParserSerializerTestsuiteRunner) so the 3E frame reference vectors in ParserSerializerTestsuite.xml are actually exercised instead of sitting unused, and wire in the protocols-slmp test-jar so the testsuite resource is on the driver test classpath. Correct the deviceCode enum fields in the testsuite from the shorthand <deviceCode>D</deviceCode> to the canonical <SlmpDeviceCode .../> element form so the vectors round-trip through parse/serialize. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
- Add SLMP protocol documentation page to the website and nav - Add release-notes entry for the new driver - Register the driver in the plc4j-driver-all bundle - Migrate the module POM to the Maven 4.1.0 model used repo-wide Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
CompletableFuture.allOf completes exceptionally when any tag future fails, and thenApply never runs on exceptional completion - so the per-tag error mapping (timeout -> REMOTE_ERROR, anything else -> INTERNAL_ERROR) was unreachable and a single failed tag failed the entire read request, contrary to the documented partial-failure isolation. Assemble the response in handle() instead. Add SlmpConnectionFailurePathTest (modeled on ModbusRtuConnectionRequestChainTest) covering timeout isolation, transport loss, send failure and unsolicited frames. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
The docs advertise W0x1A:WORD[10]; the 0x prefix, datatype and quantity were each tested separately but never combined in one address. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Language table: Java marked work-in-progress (read-only v0). Feature table: read single/multiple green, everything else red. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
Align the website wording with the code comment: 960 is this driver's conservative per-request ceiling, not asserted as the device maximum. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
The timeout cleanup ran pendingResponse = null unconditionally on the delayer thread. CompletableFuture dependents complete LIFO, so the throttle releases the next request before that cleanup runs; in that window the successor installs its own slot, which the cleanup then wiped - dropping the successor's genuine response as unsolicited and spuriously timing it out as well. Hold the slot in an AtomicReference and compare-and-clear against the owning future; claims in handleIncomingMessage/failPending use getAndSet. Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
- order the AtomicReference import per ASCII convention - state the LIFO dependent ordering as OpenJDK behavior, and note the compare-and-clear is correct regardless of it - log when a late response is dropped against an already-completed request, matching the unsolicited-frame log Signed-off-by: Jooyoung Jung <livinglikekrillin@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second increment of the SLMP roadmap in #2585, building on the merged protocol module (#2597): the Java driver (
plc4j/drivers/slmp) on the new SPI.What's in it
slmp:tcp://{host}:{port}driver (default port 5007), read-only v0: Batch Read (0x0401), word unitsD/R(decimal) andW(hex, optional0xprefix); data typesWORD(default),INT,UINT,DINT,UDINT,REAL; addresses likeD350:DINT,R200:REAL[4],W0x1A:WORD[10](each of these exact forms is unit-tested)monitoring-timer(written into each 3E frame, default 0 = wait infinitely) andrequest-timeout(client-side, default 5000 ms)maxConcurrentRequests = 1) with one pending-response slot. A timeout surfaces asREMOTE_ERRORfor that tag only; other failures asINTERNAL_ERROR; one tag's failure never fails the whole read (partial-failure isolation). The mis-attribution caveat for late responses after a timeout is documented at the slot — 3E simply cannot prevent it, so a timed-out read should be treated as unreliable by the caller.plc4j-driver-all, following the majority of drivers — but noticed UMAS isn't registered there; happy to drop the registration if you'd rather stage it the same wayValidation
DriverTestsuiteIT (API read → codec → response →PlcValue)ModbusRtuConnectionRequestChainTest): timeout isolation, transport loss mid-flight, send failure, unsolicited frame. Writing these exposed a real bug during development — the partial-failure mapping sat behindallOf(...).thenApply(...), which never runs on exceptional completion, so one failed tag failed the entire read; fixed withhandle()and now pinned by the tests0xD000subheader), and an R-device-code difference found while reading their source (avoided in the test by sticking to D/W). The throwaway harness is not part of this PR; logs and details available on requestverify(tests + JaCoCo gate) green with the branch rebased onto current develop; Apache RAT at module level: 32/32 files approved, 0 unknownBench validation on real MELSEC hardware would be very welcome — the driver is read-only, so pointing it at a test PLC is side-effect-free.
Next (not in this PR)
0x1401), Random Read (0x0403) and Multi-block (0x0406) on the driver side (wire types already merged), bit devices/units, request splitting, ASCII mode, 4E — per the staged roadmap in Contribution proposal: read-only SLMP (MELSEC-Communication 3E) driver #2585Developed with AI assistance; the wire behavior is verified against SH-080008's worked examples and cross-checked against an independent third-party implementation as noted above.