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 >
