Hi Niels,

As Łukasz pointed out, there are a thousand different combinations of how
Modbus requests can be arranged. I'm not sure there's a generic schema that
can be used to define it though.

You talked originally about splitting large reads (>125 registers) up into
smaller registers. This logic would live in a class that implements the
BaseOptimizer. This is then defined within the ModbusTCPDriver class, we
are just using the SingleTagOptimizer for Modbus at the moment.

If I were to implement this I would probably firstly try and combine tags
that are adjacent into one request until we either encounter a break in the
requested area or approach the limit of ~125 registers. This way it is
guaranteed that requests for individual requests are not broken into
smaller requests.

Kind Regards

Ben





On Sun, Jan 15, 2023 at 6:58 PM Niels Basjes <[email protected]> wrote:

> Hi Łukasz,
>
> At this point I tend towards the need for a tool that allows one to define
> the schema of a modbus device with all available values and code to convert
> them into usable stuff (like in java an actual String or Double).
> So far it seems this needs indeed flags indicating which values can and
> must be read combined (like the sync block in SunSpec).
> Then based on this a request for a set of functional values is converted
> into a set of modbus requests that follow these defined rules.
>
> Rules about an after connection delay and maximum requests per second seem
> like something that should be at the modbus level (i.e. part of plc4x).
>
> Is there an existing project that does something like this?
>
> Niels
>
> On Sun, Jan 15, 2023 at 5:22 PM Łukasz Dywicki <[email protected]>
> wrote:
>
> > I am really glad you are moving it forward and fighting it!
> >
> > It is fairly difficult to get modbus code aligned and working
> > automatically because different devices behave differently with even
> > most basic requests.
> > I remember that one of electric meters I had to work with did support
> > read multiple registers but did not support going over "empty" indexes.
> > By empty  I mean these which were not declared in the documentation,
> > even if it was still below 125 limit.
> >
> > Effectively I could draw three primary options to cover:
> > - read continuous (just keep expanding requests up to the limit)
> > - read blocks (group indexes into blocks up to limit, if they are
> > continuous)
> > - read single (read multiple registers is not supported)
> >
> > Some devices, especially older PLCs may also require extra delay after
> > data retrieval, so you have to wait between finishing one request and
> > starting another. Some inverters and official dongles made by fairly
> > large Chinese manufacturer, which brand I won't mention here, as well as
> > primitive tcp/rtu bridges, may require "after connection delay" in order
> > to establish rtu connection they use to serve tcp session.
> >
> > All this makes modbus option list rather long, compared to abilities it
> > gives!
> >
> > Cheers,
> > Łukasz
> >
> >
> > On 15.01.2023 17:05, Niels Basjes wrote:
> > > Hi,
> > >
> > > No, I'm reading many logical values where the needed registers combined
> > > exceed the 125 mark.
> > > Assume my application needs a set of values and asks for such a block
> of
> > > registers.
> > > Then the modbus library that gets the request for 200 registers can no
> > > longer reliably split it into multiple parts that yield the correct
> > value.
> > >
> > > What I understand of your S7 example (I do not know this device) seems
> > like
> > > a device that offers a single value that exceeds the limits of modbus
> and
> > > thus I expect they made it so you can fetch it step by step.
> > >
> > > I'll see if I can do a wireshark dump for you.
> > >
> > > What should I make the issue say? I currently do not see this as a bug
> or
> > > problem with plc4x.
> > >
> > > Niels
> > >
> > > On Sun, Jan 15, 2023 at 4:46 PM Christofer Dutz <
> > [email protected]>
> > > wrote:
> > >
> > >> Hi Niels,
> > >>
> > >> I think this might be related to what happens when reading Strings in
> S7
> > >> without providing a length.
> > >> In this case each string is 255 charaters long and it already exceeds
> > the
> > >> size-limit of 200 or so of a S7 1200.
> > >>
> > >> In S7 we use some code to split up multiple tags into multiple
> requests,
> > >> but rewriting the query to support automatic splitting of one single
> tag
> > >> into multiple requests is quite a bit more difficult.
> > >>
> > >> I thought you were reading multiple tags that in sum exceeded the 125
> > >> registers and for that case simply something similar to the S7 query
> > >> updater should also work for other protocols.
> > >>
> > >> Do I understand you correctly, that in your case you want to read one
> > tag,
> > >> that is bigger?
> > >>
> > >> Chris
> > >>
> > >> From: Niels Basjes <[email protected]>
> > >> Date: Sunday, 15. January 2023 at 16:38
> > >> To: [email protected] <[email protected]>
> > >> Subject: [Modbus] Handling 'too large' blocks of registers
> > >> Hi,
> > >>
> > >> A few weeks ago some code of mine was merged to limit the number of
> > >> registers that can be requested in a single ModbusTag because asking
> for
> > >> more than 125 registers in a single request will always fail (because
> of
> > >> the way modbus works).
> > >> https://github.com/apache/plc4x/pull/721
> > >>
> > >> One of the comments was asking if it can be automated in a generic way
> > to
> > >> split a "too large" request into multiple smaller requests.
> > >> So If I ask for a block of 200 registers then plc4x would simply split
> > it
> > >> into multiple requests (like 125 and 75 for example, or 100 and 100)
> and
> > >> afterwards merge the resulting registers of the two requests back
> into a
> > >> single block of 200 registers for the upstream application to analyze.
> > >>
> > >> I said I would look into this and this is what I found while doing
> some
> > >> experimenting with my real solar converter.
> > >> This device uses the SunSpec standard for defining meaning to modbus
> > >> registers.
> > >>
> > >> My current conclusion at this point is that it is impossible to handle
> > this
> > >> at the modbus level and I'm looking for you guys to challenge me in
> > this.
> > >>
> > >> Why do I say this?
> > >> One of the logical values you can retrieve is the name of the
> > Manufacturer
> > >> and the Model of the device that are both stored as UTF-8 in a set of
> 16
> > >> registers (i.e. usually 32 characters).
> > >> https://github.com/sunspec/models/blob/master/json/model_1.json#L27
> > >> https://github.com/sunspec/models/blob/master/json/model_1.json#L36
> > >>
> > >> I found that if I try to fetch only a part of this logical value I get
> > >> either an error (INVALID_ADDRESS) or bad data.
> > >> When I fetch the entire value I get the 16 registers which hold the
> > correct
> > >> data.
> > >>
> > >> Output of my test program that fetches the Model of the device (which
> > is in
> > >> my case "SB3.6-1AV-41" ).
> > >> ModbusTag[4x40021:UINT[16]]:  0x5342 0x332E 0x362D 0x3141 0x562D
> 0x3431
> > >> 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
> > >> ModbusTag[4x40021:UINT[15]]: INVALID_ADDRESS
> > >> ModbusTag[4x40022:UINT[15]]:  0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
> 0xFFFF
> > >> 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
> > >>
> > >> So if I retrieve the correct block I get it.
> > >> If I try to get 1 register less than I should I get an error.
> > >> If I try to get the registers starting from the 2nd register I get
> only
> > >> 0xFFFF (important: NO error and a PlcResponseCode.OK !!)
> > >>
> > >> I expect there to be many other modbus devices that have similar
> effects
> > >> when the logical value requires multiple registers.
> > >>
> > >> So for now I come to the conclusion that fetching only part of the
> > >> registers that make up a logical variable in general will not work and
> > (in
> > >> some cases) cannot be detected to have failed.
> > >>
> > >> At this point my assessment is that the only way to handle this is by
> > >> actually knowing the meaning of the block of registers (i.e. which
> must
> > be
> > >> read together in a single read) and work from there.
> > >>
> > >> Note that the current SunSpec definition also has the concept of a
> > 'sync'
> > >> group of points (logical values that consist of 1 or more registers)
> > which
> > >> are grouped in the specification with the intent of "indicating
> > >> that the points in the group must be read and written atomically",
> which
> > >> effectively means you cannot read them individually from the modbus
> > >> standpoint.
> > >>
> > >> Looking for your feedback on this.
> > >> Do you know of existing software to generically handle this ?
> > >>
> > >> --
> > >> Best regards / Met vriendelijke groeten,
> > >>
> > >> Niels Basjes
> > >>
> > >
> > >
> >
>
>
> --
> Best regards / Met vriendelijke groeten,
>
> Niels Basjes
>

Reply via email to