[BUG] [Modbus] Memórias em excesso com tipos customizados

Bom dia!

Gostaria de relatar um bug que observei no driver Modbus 4.0.6, onde quando usamos um bloco customizado, há um consumo excessivo de licenças E/S. Isso se trata devido a um processamento incorreto no driver, que não respeita o tamanho do bloco ao usar tipos customizados.

No meu caso, tenho 5 memórias sendo lidas (1 dword + 4 words), porém o driver está requisitando para meu server as memórias 2 até 31 ao invés de 2 até 7, e se verifico o log do driver observo que lá também ele pede 30 itens

14/10/2021 10:46:24.917 (CB3C) IO|TX:  00 23 00 00 00 06 02 03 00 02 00 1E
14/10/2021 10:46:24.918 (CB3C) IO|RX:  00 23 00 00 00 03 02 83 04
14/10/2021 10:46:24.918 (A458) DRIVER|MODBUS exception response - type 4(SLAVE DEVICE FAILURE)!
14/10/2021 10:46:24.918 (A458) DRIVER|sgets failed, input stream is not available (hr=80004005)!
14/10/2021 10:46:24.918 (A458) TAG|<== (0.001) Tag(2.0.3.2.Blob:0062E5B0[30]).ReadBlock = ERROR (hr=80004005)

Bloco no E3:

Struct customizado:

struct Prntr {
  dword totalImpressoes;
  word levelBlack;
  word levelCyan;
  word levelMagenta;
  word levelYellow;
}

Eu consigo ler o número correto de memórias se altero o tamanho do bloco para 1, porém ele só processa o primeiro item do bloco:

No log do driver:

14/10/2021 10:45:45.672 (A8B8) IO|TX:  00 1A 00 00 00 06 02 03 00 02 00 06
14/10/2021 10:45:45.673 (A8B8) IO|RX:  00 1A 00 00 00 0F 02 03 0C 00 00 46 10 00 5E 00 38 00 45 00 40
14/10/2021 10:45:45.673 (CF50) TAG|<== (0.003) Tag(2.0.3.2.Blob:005A1138[6]).ReadBlock = (10:45:45.672) array(6;HVAL) {0,17936,94,56,69,64}

Observe que a leitura de tamanho 6 se deve a dword totalImpressoras ocupar 2 endereços de memória

Essas leituras em excesso além de saírem mais caras para os usuários finais (pela necessidade de mais licenças E/S) devido ao consumo completamente desnecessário de licenças, também prejudica quem trabalha com rádios de baixa velocidade (especialmente rádios de rede serial) para estações remotas que precisam fazer requisições em bloco para evitar um número excessivo de requests poluindo a rede.

Se precisarem de ajuda para diagnosticar o problema em laboratório, estou a disposição.

Henrique

Olá @hstarosky,

Como os tipos de dados são diferentes, recomendo utilizar um tag de comunicação para o endereço dword totalImpressoes. E um bloco para os demais do tipo word.

Quando utiliza um bloco apenas, pode-se informar apenas uma operação de leitura e escrita (coluna P2/N2/B2).

Realize um teste desabilitando a propriedade EnableReadGrouping do Driver.

Olá @Gabriel!

Já fazemos isso normalmente, porém gostaríamos de criar structs padronizadas para leituras de equipamentos iguais, de forma a facilitar o desenvolvimento e manutenção.

Apesar de existir outro modo de se resolver esse problema, não muda o fato que existe um bug numa função do driver. Se essa função não deve ser utilizada, seria melhor que não fosse liberado o acesso dela para os desenvolvedores procurando essa solução.

Acredito que a melhor saída seria que o driver (quando utilizando struct) ignorasse o tamanho do bloco e ao invés de multiplicar o número de memórias consumidas pelo tamanho do bloco (como atualmente faz erroneamente) ele simplesmente buscasse a struct, processasse o valor e enfim retornasse a aplicação o número limitado do bloco (no caso do meu bloco, se eu pedisse 2 no tamanho do bloco, buscaria as 7 memórias envolvidas, transformaria os valores, e carregaria somente o index 0 e index 1 do bloco, consumindo duas tags E/S).

@hstarosky,

Poderia me enviar o log desse teste por e-mail.

Olá @hstarosky,

Como visto em sua aplicação, o problema era que existiam tags individuais que usam uma operação “struct”, e com a propriedade EnableReadGrouping habilitada, ele tentava agrupar tais tags, e ocorria o erro.

Utilizando as operação de struct apenas para os blocos, e as outras(simples) para os tags, foi possível comunicar corretamente.