Invalid CRC (RTU Modbus) - RTU06Example

Describe the bug
When using the RTU06Example with an ESP32-WROOM (NodeMCU) Development Board and Modsim64 as a server. The CRC validation fails when reading registers. It is however able to write to registers without issue.
The connection is made via UART (CP2102) to a Windows host.
Expected behavior
It is expected that CRC validation would succeed in both contexts.
To Reproduce
Install Modsim64 (demo or equivalent)
Run Example
Example code
RTU06Example (accessed 29/12/2020)
https://github.com/eModbus/eModbus/blob/d0e5329e93290076d271f374ed13c654fbf00ef7/examples/RTU06example/main.cpp
I have also attempted to add CRC to a Modbus Message manually with no difference in the outcome:
        ModbusMessage msg = ModbusMessage(1, READ_HOLD_REGISTER, 10, 1);
        RTUutils::addCRC(msg);
        err = MB.addRequest(msg, Token++);
        if (err != SUCCESS)
        {
            ModbusError e(err);
            Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
        }

Additional context
I have tried using alternative serial configurations (SERIAL8E1, SERIAL8N2, etc.) to no success.
Modbus Messages recorded via Modsim64 (over UART):

CRC Counters:

Register written to successfully:

MCU Output:
Response: serverID=1, FC=6, Token=00000457, length=6:
01 06 00 0A 12 34
Error response: E0 - Timeout
Response: serverID=1, FC=6, Token=00000459, length=6:
01 06 00 0A BE EF
Error response: E0 - Timeout

EDIT: UPDATED incorrect modscan references to modsim.

What does tell you the CRC check failing? The error message clearly is stating a TIMEOUT event, so my first idea would be to look for the Modscan64 response and your timeout settings.

Another thing: is Modscan64 supposed to work as a server as well? The references I found on the Net were for a client use only.

For reference: the CRC implementation in this lib is the one given as an example in the modbus specification: https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf

Correction: Modscan64 does not know about a dedicated CRC error response, so it will simply not respond at all. This is the reason for ModbusClientRTU to report a TIMEOUT.
Another thing: is Modscan64 supposed to work as a server as well? The references I found on the Net were for a client use only.

My apologies, I am using ModSim64, I apologize for the confusion.
I will test the Modbus implementation with some PLCs and see if it functions as expected. I'm not quite sure why it wouldn't be working, as we use Modsim32/64 (& Modscan32/64) quite extensively to test PLCs and Modbus devices. I was hoping it might have been an obvious mistake on my part.
I tested with diagslave http://www.modbusdriver.com/diagslave.html and it seems to be working, I am still hesitant to write this off as an issue with Modsim32 until I have a clear understanding of why its not working.

Please keep us posted about your findings.

Ok so I spent a lot of time testing over NYE, and here is my findings:
I uploaded the following code to the ESP32 in the void_setup section:
[Notice how the same operations are repeated twice].
// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

I used several PLCs to test with and all had the same error output as follows:
Error response: E5 - Packet length error
Error response: E4 - Server ID mismatch
Error response: E0 - Timeout
Response: serverID=3, FC=3, Token=000007BA, length=5:
03 03 02 0B B8

Interestingly if I just have the following:
// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

Communication works as expected.

I realised there must have been an issue with the output, so I connected a logic analyser and confirmed the output was not as anticipated.  I have attached the logic analyser capture from running this code. The checksums are invalid and the more tests I ran, the more quirky behaviour I found.
Specifically, if I implemented two of the same read/write holding register operations the communication does not work. If I write, read and write multiple registers it works as expected.
Hopefully the logic analyser capture gives context to this timing issue, but it seems there is a bug in the Modbus output. Although, I might be overlooking something? I have also attached a copy of the code so the issue can be replicated.

Data Captures:
RAW:
BIT_CAPTURE.zip
MODBUS:
CAPTURE.zip
CODE:
CODE.zip

It doesn't matter what Modbus server I have, the issue is replicated with different PLCs & MCU's via direct UART using a variety of Serial settings.
Let me know if you need any more information, I have setup two microcontrollers (host & client) with a logic analyser for testing.

Ok so I spent a lot of time testing over NYE, and here is my findings:
I uploaded the following code to the ESP32 in the void_setup section:
[Notice how the same operations are repeated twice].
// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

I used several PLCs to test with and all had the same error output as follows:
Error response: E5 - Packet length error
Error response: E4 - Server ID mismatch
Error response: E0 - Timeout
Response: serverID=3, FC=3, Token=000007BA, length=5:
03 03 02 0B B8

Interestingly if I just have the following:
// Now write 0xBEEF to it
err = MB.addRequest(Token++, 3, WRITE_HOLD_REGISTER, 2, 0xBEEF);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

// Read it again to verify
err = MB.addRequest(Token++, 3, READ_HOLD_REGISTER, 2, 1);
if (err != SUCCESS)
{
    ModbusError e(err);
    Serial.printf("Error creating request: %02X - %s\n", (int)e, (const char *)e);
}

Communication works as expected.

I realised there must have been an issue with the output, so I connected a logic analyser and confirmed the output was not as anticipated.  I have attached the logic analyser capture from running this code. The checksums are invalid and the more tests I ran, the more quirky behaviour I found.
Specifically, if I implemented two of the same read/write holding register operations the communication does not work. If I write, read and write multiple registers it works as expected.
Hopefully the logic analyser capture gives context to this timing issue, but it seems there is a bug in the Modbus output. Although, I might be overlooking something? I have also attached a copy of the code so the issue can be replicated.

Data Captures:
RAW:
BIT_CAPTURE.zip
MODBUS:
CAPTURE.zip
CODE:
CODE.zip

It doesn't matter what Modbus server I have, the issue is replicated with different PLCs & MCU's via direct UART using a variety of Serial settings.
Let me know if you need any more information, I have setup two microcontrollers (host & client) with a logic analyser for testing.

Thanks a lot for the materials. I will have a look at this today.
Without having done that yet, I would bet on out-of-sync timing on the RTU Modbus. Did you see the lengthy comment in RTUutils.cpp on the Serial handling issue the arduino-esp32 core has? You will need to either modify the esp-hal_uart.cc as described or accept the much longer interval between requests.

Thanks a lot for the materials. I will have a look at this today.
Without having done that yet, I would bet on out-of-sync timing on the RTU Modbus. Did you see the lengthy comment in RTUutils.cpp on the Serial handling issue the arduino-esp32 core has? You will need to either modify the esp-hal_uart.cc as described or accept the much longer interval between requests.

I tested modifying esp-hal_uart.c with     uart->dev->conf1.rxfifo_full_thrhd = 1; the same issues persist.

I tested modifying esp-hal_uart.c with     uart->dev->conf1.rxfifo_full_thrhd = 1; the same issues persist.

Dang. Could you perhaps put a #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE at the start of both RTUutils.cpp and ModbusServerRTU.cpp, and MBUlogLvl = LOG_LEVEL_VERBOSE; in your setup()  and then run the stuff again? The extended log may give additional information.

Dang. Could you perhaps put a #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE at the start of both RTUutils.cpp and ModbusServerRTU.cpp, and MBUlogLvl = LOG_LEVEL_VERBOSE; in your setup()  and then run the stuff again? The extended log may give additional information.

In your code I found
// Set up Serial2 connected to Modbus RTU
// (Fill in your data here!)
  Serial2.begin(19200, SERIAL_8E1, GPIO_NUM_16, GPIO_NUM_17);

The SERIAL_8E1 is at least uncommon - are you sure your server does even parity? I never saw anything else but SERIAL_8N1 before.
I can not take much information from the two capture CSVs, I am afraid. Is your LA able to do a byte printout on the Serial Tx and Rx lines?
I reckon the verbose log may be helpful indeed.

In your code I found
// Set up Serial2 connected to Modbus RTU
// (Fill in your data here!)
  Serial2.begin(19200, SERIAL_8E1, GPIO_NUM_16, GPIO_NUM_17);

The SERIAL_8E1 is at least uncommon - are you sure your server does even parity? I never saw anything else but SERIAL_8N1 before.
I can not take much information from the two capture CSVs, I am afraid. Is your LA able to do a byte printout on the Serial Tx and Rx lines?
I reckon the verbose log may be helpful indeed.

@thehaxxa did you get any further in the meantime?

@thehaxxa did you get any further in the meantime?

Seems to be irrelevant in the meantime.

Seems to be irrelevant in the meantime.

@Miq1 I spent additional time testing the eModbus Library in several additional scenarios.
I would like to confirm the comment in the esp-hal_uart.cc did end up resolving my timing issues, more specifically setting uart->dev->conf1.rxfifo_full_thrhd = 1; resolved my issues. PlatformIO was compiling using Windows Subsystem for Linux (WSL)  instead of the Windows environment. Thus my initial change was not compiled and I incorrectly concluded the change did not fix the issue.
Thank you for all your time and support diagnosing the connection.

Overall the library is very well documented and is nice to work with in contrast to other Modbus libraries on Embedded platforms.
I would however propose the comment made in esp-hal_uart.c is added to the documentation (provided on Github). User's unfamiliar with this library may assume, the library is not working. While searching through code to find comments on the subject is tedious and elusive. As the library targets the ESP32 platform, I think it would be a good addition to the documentation. Thoughts?
In any case, thanks once again for your help and for producing a well designed and documented library.

@Miq1 I spent additional time testing the eModbus Library in several additional scenarios.
I would like to confirm the comment in the esp-hal_uart.cc did end up resolving my timing issues, more specifically setting uart->dev->conf1.rxfifo_full_thrhd = 1; resolved my issues. PlatformIO was compiling using Windows Subsystem for Linux (WSL)  instead of the Windows environment. Thus my initial change was not compiled and I incorrectly concluded the change did not fix the issue.
Thank you for all your time and support diagnosing the connection.

Overall the library is very well documented and is nice to work with in contrast to other Modbus libraries on Embedded platforms.
I would however propose the comment made in esp-hal_uart.c is added to the documentation (provided on Github). User's unfamiliar with this library may assume, the library is not working. While searching through code to find comments on the subject is tedious and elusive. As the library targets the ESP32 platform, I think it would be a good addition to the documentation. Thoughts?
In any case, thanks once again for your help and for producing a well designed and documented library.

Thank you for your report and kind words. 👍
Initiated by your issue I already did what you are proposing, the advice to change the core code now is part of the Requirements section of the docs.

Thank you for your report and kind words. 👍
Initiated by your issue I already did what you are proposing, the advice to change the core code now is part of the Requirements section of the docs.

@Miq1 can you point me out at which section does the info about changing core code currently resides?
Can't seem to find it in the requirements section of the docs (or am i missing something?)
Also it seems the lengthy comment in RTUutils.cpp has been perhaps removed, right?
Just to give you'll some context, I'm getting error E5 for a just single read operation utilizing the RTU06 example.

@Ebrahim1604 we changed the complete timeout handling with RTU in the last but one release, and the core patch is no longer required, too, as the necessary change is done temporarily for the running program in UARTinit().
The E5 packet length error is indicating some other reason. Can yo please post the relevant parts of your code to let us have a look?

Sure, here are the details.
Trying to setup a Rtu cleint in LOLIN D32 PRO
The rtu server is a pressure sensor as following: https://download.keller-druck.com/api/download/muQjLg2dGMJAbgLYSAHreT/en/latest.pdf (If you'd like to have a look section 4 is where you can)
The rs485 to uart convertor being employed here is as follows: https://www.robotshop.com/uk/sfe-uart-to-rs-485-converter.html (Not auto half duplex so requires a rts pin)
Here is the modified .ino file where I try to read the value at register 0x0200, which is for setting the baud rate of the server, default being 9600 the bit0:bit2 should be 0:
// =================================================================================================
// eModbus: Copyright 2020 by Michael Harwerth, Bert Melis and the contributors to ModbusClient
//               MIT license - see license.md for details
// =================================================================================================

// Example code to show the usage of the eModbus library.
// Please refer to root/Readme.md for a full description.

// Includes: <Arduino.h> for Serial etc.

/*
 Pin connections:
      LOLIN d32 pro            Uart to rs485 convertor
    1)   GPIO 12--------------------------TX
    2)   GPIO 11--------------------------RX
    3)   GPIO 15--------------------------RTS
    4)    3.3V----------------------------VCC
    5)    GND-----------------------------GND
 */

// Include the header for the ModbusClient RTU style
#include "ModbusClientRTU.h"

// For demonstration, use the LOG statements for output
#include "Logging.h"

const byte rxd = 12;
const byte txd = 13;
const byte rts = 15;

#define demo_addr 0x0200 //bit0, bit1 & bit2 are for baud rate, default 9600

// Create a ModbusRTU client instance
ModbusClientRTU MB(Serial2, rts);

// Define an onData handler function to receive the regular responses
// Arguments are Modbus server ID, the function code requested, the message data and length of it,
// plus a user-supplied token to identify the causing request
void handleData(ModbusMessage response, uint32_t token)
{
  // Only print out result of the "real" example - not the request preparing the field
  if (token > 1111) {
    LOG_N("Response: serverID=%d, FC=%d, Token=%08X, length=%d:\n", response.getServerID(), response.getFunctionCode(), token, response.size());
    HEXDUMP_N("Data", response.data(), response.size());
  }
}

// Define an onError handler function to receive error responses
// Arguments are the error code returned and a user-supplied token to identify the causing request
void handleError(Error error, uint32_t token)
{
  // ModbusError wraps the error code and provides a readable error message for it
  ModbusError me(error);
  LOG_E("Error response: %02X - %s\n", (int)me, (const char *)me);
}

// Setup() - initialization happens here
void setup() {
// Init Serial monitor
  Serial.begin(9600);
  while (!Serial) {}
  Serial.println("__ Kellar33x Modbus demo code __");

// Set up Serial2 connected to Modbus RTU
// (Fill in your data here!)
  Serial2.begin(9600, SERIAL_8N1, rxd, txd);

// Set up ModbusRTU client.
// - provide onData handler function
  MB.onDataHandler(&handleData);
// - provide onError handler function
  MB.onErrorHandler(&handleError);
// Set message timeout to 2000ms
  MB.setTimeout(2000);
// Start ModbusRTU background task
  MB.begin();

  uint32_t Token = 1111;

// Create request by
// - token to match the response with the request.
// - server ID = 1
// - function code = 0x03 (read holding register)
// - address to read = demo_addr
// - data words to read = 1
//
// If something is missing or wrong with the call parameters, we will immediately get an error code
// and the request will not be issued

// Read register
 Error err = MB.addRequest(Token++, 1, READ_HOLD_REGISTER, demo_addr, 1);
  if (err!=SUCCESS) {
    ModbusError e(err);
    LOG_E("Error creating request: %02X - %s\n", (int)e, (const char *)e);
  }

// loop() - nothing done here today!
void loop()
{
}

Here is the Serial monitor output, where along with those garbage values(not sure how that appeared) the E5 packet length error is seen:

I hope that's enough. Thanks for your help!

I see. What makes me frown in the first row ist section 4.2 of the Keller documentation where they state that their CRC has a different byte order than Modbus. WTF?
Can you recompile your sketch with -DLOG_LEVEL=6 and post the log output here? That should give us hints on what is going back and forth.

@Miq1 sure ill do that, but i think what you're referring to is kellar protocol.
It is their own custom protocol which is slightly different from Modbus.
But I prefer going with Modbus as the api they provided for Kellar has tons of issues and modbus is quite popular & has tons of resources as opposed to kellar.

@Ebrahim1604 any progress on this?

Hello, Apologies for the delay, have been sick past week and just got back to work.
I just wanted to clarify, I'm using arduino ide and not paltform.io so I'm not entirely sure how can i recompile the code with  the flag -DLOG_LEVEL=6
Have enabled the the verbose output in the File->Preferences section of the Ardunio IDE.
Got the following output:

ets Jun  8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8
_ Kellar33x Modbus demo code _
Setup() function running on core: 1
handle error() function running on core: 0
[E] 2138| Kellar_ESP32.ino     [  48] handleError: Error response: E0 - Timeout

<<<

Ok as an update, I added the line : #define LOG_LEVEL LOG_LEVEL_VERBOSE above the #include "Logging.h", so this is the code:
/*
 Pin connections:

      LOLIN d32 pro            Uart to rs485 convertor
    1)   GPIO 13--------------------------TX
    2)   GPIO 12--------------------------RX
    3)   GPIO 15--------------------------RTS
    4)    3.3V----------------------------VCC
    5)    GND-----------------------------GND
 */

// Include the header for the ModbusClient RTU style
#include "ModbusClientRTU.h"

#define LOG_LEVEL LOG_LEVEL_VERBOSE
// For demonstration, use the LOG statements for output
#include "Logging.h"

const byte rxd = 12;
const byte txd = 13;
const byte rts = 15;

#define demo_addr 0x0200

// Create a ModbusRTU client instance
ModbusClientRTU MB(Serial2, rts);

// Define an onData handler function to receive the regular responses
// Arguments are Modbus server ID, the function code requested, the message data and length of it,
// plus a user-supplied token to identify the causing request
void handleData(ModbusMessage response, uint32_t token)
{
  Serial.print("handledata() function running on core: ");
  Serial.println(xPortGetCoreID());
  // Only print out result of the "real" example - not the request preparing the field
  if (token > 1111) {
    LOG_N("Response: serverID=%d, FC=%d, Token=%08X, length=%d:\n", response.getServerID(), response.getFunctionCode(), token, response.size());
    HEXDUMP_N("Data", response.data(), response.size());
  }
}

// Define an onError handler function to receive error responses
// Arguments are the error code returned and a user-supplied token to identify the causing request
void handleError(Error error, uint32_t token)
{
  Serial.print("handle error() function running on core: ");
  Serial.println(xPortGetCoreID());
  // ModbusError wraps the error code and provides a readable error message for it
  ModbusError me(error);
  LOG_E("Error response: %02X - %s\n", (int)me, (const char *)me);
}

// Setup() - initialization happens here
void setup() {
// Init Serial monitor
  Serial.begin(115200);
  while (!Serial) {}
  Serial.println("__ Kellar33x Modbus demo code __");

  Serial.print("Setup() function running on core: ");
  Serial.println(xPortGetCoreID());
// Set up Serial2 connected to Modbus RTU
// (Fill in your data here!)
  Serial2.begin(9600, SERIAL_8N1, rxd, txd);

// Set up ModbusRTU client.
// - provide onData handler function
  MB.onDataHandler(&handleData);
// - provide onError handler function
  MB.onErrorHandler(&handleError);
// Set message timeout to 2000ms
  MB.setTimeout(2000);
// Start ModbusRTU background task
  MB.begin();

  uint32_t Token = 1111;

// Create request by
// - token to match the response with the request.
// - server ID = 1
// - function code = 0x03 (read holding register)
// - address to read = word 10
// - data words to read = 1
//
// If something is missing or wrong with the call parameters, we will immediately get an error code
// and the request will not be issued

// Read register
 Error err = MB.addRequest(Token++, 1, READ_HOLD_REGISTER, demo_addr, 1);
  if (err!=SUCCESS) {
    ModbusError e(err);
    LOG_E("Error creating request: %02X - %s\n", (int)e, (const char *)e);
  }

/*
// Now write 0xBEEF to it
  err = MB.addRequest(Token++, 1, WRITE_HOLD_REGISTER, 10, 0xBEEF);
  if (err!=SUCCESS) {
    ModbusError e(err);
    LOG_E("Error creating request: %02X - %s\n", (int)e, (const char *)e);
  }

// Read it again to verify
  err = MB.addRequest(Token++, 1, READ_HOLD_REGISTER, 10, 1);
  if (err!=SUCCESS) {
    ModbusError e(err);
    LOG_E("Error creating request: %02X - %s\n", (int)e, (const char *)e);
  }

// Provoke an error just to show it
  err = MB.addRequest(Token++, 1, USER_DEFINED_44, 10, 1);
  if (err!=SUCCESS) {
    ModbusError e(err);
    LOG_E("Error creating request: %02X - %s\n", (int)e, (const char *)e);
  }
*/
}
// loop() - nothing done here today!
void loop()
{
}

For some reason, the error message went from E0 to E4 i.e. server id mismatch which is extremely weird as the server id of the sensor is set to 1 and verified. Here is the output:
ets Jun  8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8
_ Kellar33x Modbus demo code _
Setup() function running on core: 1
handle error() function running on core: 0
[E] 153| Kellar_ESP32.ino     [  51] handleError: Error response: E4 - Server ID mismatch

In the IDE unfortunately it is not possible to set compiler flags on the fly, so you need to change the default log level in the Logging.h file. There is a line close to the beginning stating #define LOG_LEVEL LOG_LEVEL_ERROR. Please change to LOG_LEVEL_VERBOSE.
You will have to change that back at a time where you will want to get rid of the additional output.

ok so after changing the logging.h file, here is the output:

ets Jun  8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8
_ Kellar33x Modbus demo code _
Setup() function running on core: 1
[D] 28| ModbusClientRTU.cpp  [ 100] setTimeout: Timeout set to 2000
[D] 28| ModbusClientRTU.cpp  [  72] begin: Worker task<PHONE_NUMBER> started. Interval=3645
[V] 36| ModbusMessage.cpp    [ 529] checkData: Check data #3
[D] 41| ModbusClientRTU.cpp  [ 107] addRequestM: request for 01/03
[D] 47| ModbusClientRTU.cpp  [ 156] addToQueue: RC=01
[D] 52| ModbusClientRTU.cpp  [ 118] addRequestM: RC=00
[D] 128| ModbusClientRTU.cpp  [ 174] handleConnection: Pulled request from queue
[D] Sent packet: @3FFB9804/6:
| 0000: 01 03 02 00 00 01                                 |......          |
[D] 137| ModbusClientRTU.cpp  [ 179] handleConnection: Request sent.
[D] Received packet: @3FFB984C/9:
| 0000: 00 01 03 02 00 00 B8 44  00                       |.......D.       |
[D] 154| ModbusClientRTU.cpp  [ 185] handleConnection: Data response (9 bytes) received.
[V] Data: @3FFB984C/9:
| 0000: 00 01 03 02 00 00 B8 44  00                       |.......D.       |
[D] 169| ModbusClientRTU.cpp  [ 214] handleConnection: Response generated.
[V] Response packet: @3FFB9804/3:
| 0000: 01 83 E4                                          |...             |
handle error() function running on core: 0
[E] 189| Kellar_demo_1.ino    [  52] handleError: Error response: E4 - Server ID mismatch

Also tried changing tx and rx, the output was as follows:

ets Jun  8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8
_ Kellar33x Modbus demo code _
Setup() function running on core: 1
[D] 28| ModbusClientRTU.cpp  [ 100] setTimeout: Timeout set to 2000
[D] 28| ModbusClientRTU.cpp  [  72] begin: Worker task<PHONE_NUMBER> started. Interval=3645
[V] 36| ModbusMessage.cpp    [ 529] checkData: Check data #3
[D] 41| ModbusClientRTU.cpp  [ 107] addRequestM: request for 01/03
[D] 47| ModbusClientRTU.cpp  [ 156] addToQueue: RC=01
[D] 52| ModbusClientRTU.cpp  [ 118] addRequestM: RC=00
[D] 128| ModbusClientRTU.cpp  [ 174] handleConnection: Pulled request from queue
[D] Sent packet: @3FFB9804/6:
| 0000: 01 03 02 00 00 01                                 |......          |
[D] 137| ModbusClientRTU.cpp  [ 179] handleConnection: Request sent.
[D] Received packet: @3FFBDB4C/1:
| 0000: E0                                                |.               |
[D] 2142| ModbusClientRTU.cpp  [ 185] handleConnection: Error response (1 bytes) received.
[V] Data: @3FFBDB4C/1:
| 0000: E0                                                |.               |
[D] 2157| ModbusClientRTU.cpp  [ 214] handleConnection: Response generated.
[V] Response packet: @3FFBDB4C/3:
| 0000: 01 83 E0                                          |...             |
handle error() function running on core: 0
[E] 2177| Kellar_demo_1.ino    [  52] handleError: Error response: E0 - Timeout

Wonderful, thank you.
The second request is ending in a TIMEOUT and may be a consequence of the first.
But the first has some remarkable oddities: the request correctly is asking for just one register at address 0x0200.
The response is 00 01 03 02 00 00 B8 44 00, led in by a 00 that is not supposed to be there, since the first regular byte is 01, the server ID. Then follows the function code 03 - okay - and the next is supposed the length byte: 02, what is what we should expect,a single register has 2 bytes.The next two bytes are the register content 00 00, the next two bytes supposedly are the CRC. After that again comes a stray 00.
So it looks like the server is enclosing a correct message in 00 bytes - not standard and driving a standard client nuts... The message to a conforming client looks like "server id 00, function code 01, 2 coils to be expected.  Both are 0, the CRC of 00 B8 is wrong and ooops: another two bytes?!?"
I would suggest to refer to the sensor's specifications again to see if this behaviour may be corrected by configuration.

Thanks for the inputs @Miq1 , so I'll try to list out what I found:
Since I'm trying to read 0x0200 which is basically the Serial configuration register & for 9600 baud rate and 8N1 serial configuration, the output data should be 2 bytes with value 00 00.
So, that makes our frame as:

01 03 02 00 00 CRC_L  CRC_H

After calculating the crc its value comes out as 0x44B8, so the exact expectd response frame should be:

01 03 02 00 00 B8 44

Now comparing this with our actual response:

00 01 03 02 00 00 B8 44 00

So as you suggested, these 00 bytes before & after are responsible for this mess. I'm not sure why exactly these bytes are being sent before & after the actual frame by the sensor. Is there anything I can do about it?

I simply do not know, I am afraid. These 00 bytes must be generated by the sensor for some purpose, so it would be interesting to learn the rationale behind. Even better would be some means to have these bytes omitted.
I will have a look at the sensor specs you have linked above to find a clue, but would ask you to do the same or even contact the manufacturer regarding that. The response is not a valid Modbus message, so if they claim to support Modbus, they must do better 😁

The documentation is okay, there the Modbus messages are described as according to the standard. I found no indication whatsoever that the framing 00 bytes are intentional.
If I was concerned, my next step would be to attach a logic analyzer to the sensor side serial interface, to see if the 00 bytes do come together with the message proper or are artifacts.
I suppose you do have a proper RS485 termination with resistors? Usually on the client end B- is connected by a 5K resistor to GND, A+ with another 5K resistor to Vcc. Between A+ and B- an 120 Ohms resistor is recommended.

Closing this again - the user's problemsseems to be solved.

Hello (yes it's me again), I have the same issue with another modbus device
ie:

I'm also on even parity (8E1), but even with none (8N1), the two 00 bytes occurs, i'm looking forward to solve this right now

The server seems to send the two 00 bytes like a sort of wrapper. Parity is not involved, as the parity bits are stripped off on lower protocol levels.

How to get trough this wrapper? I checked configuration of the external mb system and I can do nothing except change baudrate parity and stop bits

Logic analyzer time again, I am afraid... Can you try to catch the native message the server is sending, to sort out potential library issues?

I think the NULL bytes (00) are misleading.
ModSim works fine and responds perfectly when these are present in the incoming message....however, if a modbus server is inserting NULL bytes in the reply, this library quite rightly fails because the Modbus packet should start with the responding address and end with a checksum.
Perhaps a 'fix' for this is to modify RTUutils::receive to ignore prefixed NULL bytes, and flush after checksum?

Okay, other issue, the analyzer don't work anymore, I come back a bit later to make it work

I think the NULL bytes (00) are misleading.
ModSim works fine and responds perfectly when these are present in the incoming message....however, if a modbus server is inserting NULL bytes in the reply, this library quite rightly fails because the Modbus packet should start with the responding address and end with a checksum.
Perhaps a 'fix' for this is to modify RTUutils::receive to ignore prefixed NULL bytes, and flush after checksum?

That would cover a symptom and not solve the root cause, I am afraid. The Modbus standard is the guideline for our library and does not mention any lead-in or lead-out zero bytes at all. I rather would like to learn what is causing these bytes. If it is a non-standard sensor, we may consider adding an option to cope with these; it also may be a fault of the lib I would like to weed out in case.

I just made a quick patch
// Unwrap unnecessary 00 Bytes
uint16_t ModbusMessage::unwrap() {
  MM_data.erase(MM_data.begin());
  MM_data.pop_back();
  return MM_data.size();
}

I will test a bit later with logic analyzer

Hello @Miq1 @KevinDesbonnets
I almost forgot about this thread until I received a notification again today, I would like to add an update on how I tackled this issue.
@Miq1 had suggested to check the termination resistors whether if they were in place or not, turns out they were not for the converter I was using. But the issue remained even after adding those resistors.
I had no choice but to modify the Rtuutils.cpp file to filter out unnecessary stray bits. But then again, the error was not reproducible in all the readings. As opposed to only getting 00 bytes before and after the actual readings, these are the packets i received after trying to read data from other addresses:

00 01 03 04 FF FF FF FF  FB A7 00
14 F8 00 01 03 04 FF FF  FF FF FB A7 00
00 00 00 00 00 01 03 02  00 0B F9 83 00
B8 36 01 03 02 1F 1E 30  7C 00

So @KevinDesbonnets I suggest you verify this too for multiple addresses of different data lengths before putting it in place for the final system.
At last I had to prepare a patch encompassing an algorithm which will filter out data in standard modbus format. I knew the received packet should be in following format always for the data bits at addresses I was requesting for:

01 03 0X
where 0X = no of bytes, which in my case was always 2 or 4. So the rest of the packet would have either 2 or 4 bytes accordingly.

So here is the modified Rtuutils.cpp file I'm currently using which works:
// =================================================================================================
// eModbus: Copyright 2020 by Michael Harwerth, Bert Melis and the contributors to eModbus
//               MIT license - see license.md for details
// =================================================================================================
#include "options.h"
#include "ModbusMessage.h"
#include "RTUutils.h"
#undef LOCAL_LOG_LEVEL
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
#include "Logging.h"

// calcCRC: calculate Modbus CRC16 on a given array of bytes
uint16_t RTUutils::calcCRC(const uint8_t *data, uint16_t len) {
  // CRC16 pre-calculated tables
  const uint8_t crcHiTable[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40
  };

  const uint8_t crcLoTable[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
    0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
    0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
    0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
    0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
    0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
    0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
    0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
    0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
    0x40
  };

  register uint8_t crcHi = 0xFF;
  register uint8_t crcLo = 0xFF;
  register uint8_t index;

  while (len--) {
    index = crcLo ^ *data++;
    crcLo = crcHi ^ crcHiTable[index];
    crcHi = crcLoTable[index];
  }
  return (crcHi << 8 | crcLo);
}

// calcCRC: calculate Modbus CRC16 on a given message
uint16_t RTUutils::calcCRC(ModbusMessage msg) {
  return calcCRC(msg.data(), msg.size());
}

// validCRC #1: check the given CRC in a block of data for correctness
bool RTUutils::validCRC(const uint8_t *data, uint16_t len) {
  return validCRC(data, len - 2, data[len - 2] | (data[len - 1] << 8));
}

// validCRC #2: check the CRC of a block of data against a given one for equality
bool RTUutils::validCRC(const uint8_t *data, uint16_t len, uint16_t CRC) {
  uint16_t crc16 = calcCRC(data, len);
  if (CRC == crc16) return true;
  return false;
}

// validCRC #3: check the given CRC in a message for correctness
bool RTUutils::validCRC(ModbusMessage msg) {
  return validCRC(msg.data(), msg.size() - 2, msg[msg.size() - 2] | (msg[msg.size() - 1] << 8));
}

// validCRC #4: check the CRC of a message against a given one for equality
bool RTUutils::validCRC(ModbusMessage msg, uint16_t CRC) {
  return validCRC(msg.data(), msg.size(), CRC);
}

// addCRC: calculate the CRC for a given RTUMessage and add it to the end
void RTUutils::addCRC(ModbusMessage& raw) {
  uint16_t crc16 = calcCRC(raw.data(), raw.size());
  raw.push_back(crc16 & 0xff);
  raw.push_back((crc16 >> 8) & 0xFF);
}

// calculateInterval: determine the minimal gap time between messages
uint32_t RTUutils::calculateInterval(HardwareSerial& s, uint32_t overwrite) {
  uint32_t interval = 0;

  // silent interval is at least 3.5x character time
  interval = 35000000UL / s.baudRate();  // 3.5 * 10 bits * 1000 µs * 1000 ms / baud
  if (interval < 1750) interval = 1750;       // lower limit according to Modbus RTU standard
  // User overwrite?
  if (overwrite > interval) {
    interval = overwrite;
  }
  return interval;
}

// UARTinit: modify the UART FIFO copy trigger threshold
// This is normally set to 112 by default, resulting in short messages not being
// recognized fast enough for higher Modbus bus speeds
// Our default is 1 - every single byte arriving will have the UART FIFO
// copied to the serial buffer.
int RTUutils::UARTinit(HardwareSerial& serial, int thresholdBytes) {
  int rc = 0;
#if NEED_UART_PATCH
  // Is the threshold value valid? The UART FIFO is 128 bytes only
  if (thresholdBytes > 0 && thresholdBytes < 128) {
    // Yes, it is. Try to identify the Serial/Serial1/Serial2 the user has provided.
    // Is it Serial (UART0)?
    if (&serial == &Serial) {
      // Yes. get the current value and set ours instead
      rc = UART0.conf1.rxfifo_full_thrhd;
      UART0.conf1.rxfifo_full_thrhd = thresholdBytes;
      LOG_D("Serial FIFO threshold set to %d (was %d)\n", thresholdBytes, rc);
    // No, but perhaps is Serial1?
    } else if (&serial == &Serial1) {
      // It is. Get the current value and set ours.
      rc = UART1.conf1.rxfifo_full_thrhd;
      UART1.conf1.rxfifo_full_thrhd = thresholdBytes;
      LOG_D("Serial1 FIFO threshold set to %d (was %d)\n", thresholdBytes, rc);
    // No, but it may be Serial2
    } else if (&serial == &Serial2) {
      // Found it. Get the current value and set ours.
      rc = UART2.conf1.rxfifo_full_thrhd;
      UART2.conf1.rxfifo_full_thrhd = thresholdBytes;
      LOG_D("Serial2 FIFO threshold set to %d (was %d)\n", thresholdBytes, rc);
    // None of the three, so we are at an end here
    } else {
      LOG_W("Unable to identify serial\n");
    }
  } else {
    Serial.printf("Threshold must be between 1 and 127! (was %d)", thresholdBytes);
  }
#endif
  // Return the previous value in case someone likes to see it.
  return rc;
}

// send: send a message via Serial, watching interval times - including CRC!
void RTUutils::send(HardwareSerial& serial, uint32_t& lastMicros, uint32_t interval, RTScallback rts, const uint8_t *data, uint16_t len) {
  uint16_t crc16 = calcCRC(data, len);

  // Clear serial buffers
  while (serial.available()) serial.read();

  // Respect interval
  if (micros() - lastMicros < interval) delayMicroseconds(interval - (micros() - lastMicros));

  // Toggle rtsPin, if necessary
  rts(HIGH);
  // Write message
  serial.write(data, len);
  // Write CRC in LSB order
  serial.write(crc16 & 0xff);
  serial.write((crc16 >> 8) & 0xFF);
  serial.flush();
  // Toggle rtsPin, if necessary
  rts(LOW);

  HEXDUMP_D("Sent packet", data, len);

  // Mark end-of-message time for next interval
  lastMicros = micros();
}

// send: send a message via Serial, watching interval times - including CRC!
void RTUutils::send(HardwareSerial& serial, uint32_t& lastMicros, uint32_t interval, RTScallback rts, ModbusMessage raw) {
  send(serial, lastMicros, interval, rts, raw.data(), raw.size());
}

uint8_t* clean_data(uint8_t *buffer1, register uint16_t bufferPtr, int* len)
{
  int trigger1 = 0;
  int trigger2 = 0;
  int count1 = 0;
  int count2 = 0;
  uint8_t temp1;
  uint8_t temp2;

  static uint8_t buffer2[9];
  static uint8_t buffer3[7];

  for (int i=0; i<bufferPtr; i++)
    {
        if (buffer1[i]==0x01 && trigger1==0)
        {
            temp1 = buffer1[i];
            trigger1 = 1;
        }

        else if (trigger1 == 1 && count2==0)
        {
            if (buffer1[i-1]==0x01 && buffer1[i]==0x03)
            {
                temp2 = buffer1[i];
            }

            else if(buffer1[i-2]==0x01 && buffer1[i-1]==0x03)
            {
                if(buffer1[i] == 0x04)
                {
                    buffer2[0] = temp1;
                    buffer2[1] = temp2;
                    buffer2[2] = buffer1[i];
                    count2 = 4;
                    trigger2 = 1;
                    *len = 1;
                }

                else if(buffer1[i] == 0x02)
                {
                    buffer3[0] = temp1;
                    buffer3[1] = temp2;
                    buffer3[2] = buffer1[i];
                    count2 = 2;
                    trigger2 = 1;
                    *len = 0;
                }
                else
                {
                    trigger1 = 0;
                }

            }
            else
            {
                trigger1 = 0;
            }

        }

        else if (trigger2 == 1)
        {

            if (count2 == 4)
            {
                if(count1 <= count2+2)
                {
                    buffer2[count1 + 3] = buffer1[i];
                    count1 = count1 + 1;
                }
            }

            if (count2 == 2)
            {
                if(count1 <= count2+2)
                {
                    buffer3[count1 + 3] = buffer1[i];
                    count1 = count1 + 1;
                }

            }
        }
  }

  if (count2 == 4)
  {
    return buffer2;
    }

   else
   {
    return buffer3;
    }

}

// receive: get (any) message from Serial, taking care of timeout and interval
ModbusMessage RTUutils::receive(HardwareSerial& serial, uint32_t timeout, uint32_t& lastMicros, uint32_t interval) {
  // Allocate initial receive buffer size: 1 block of BUFBLOCKSIZE bytes
  const uint16_t BUFBLOCKSIZE(512);
  uint8_t *buffer = new uint8_t[BUFBLOCKSIZE];
  uint8_t *buffer_;

  ModbusMessage rv;

  // Index into buffer
  register uint16_t bufferPtr = 0;
  // Byte read
  register int b;
  // Flag for successful read cycle
  bool hadBytes = false;
  // Next buffer limit

  // State machine states
  enum STATES : uint8_t { WAIT_DATA = 0, IN_PACKET, DATA_READ, FINISHED };
  register STATES state = WAIT_DATA;

  // Timeout tracker
  uint32_t TimeOut = millis();

  // interval tracker
  uint32_t intervalEnd = micros();

  while (state != FINISHED) {
    switch (state) {
    // WAIT_DATA: await first data byte, but watch timeout
    case WAIT_DATA:
      if (serial.available()) {
        state = IN_PACKET;
        intervalEnd = micros();
      } else {
        if (millis() - TimeOut >= timeout) {
          rv.push_back(TIMEOUT);
          state = FINISHED;
        }
      }
      delay(1);
      break;
    // IN_PACKET: read data until a gap of at least _interval time passed without another byte arriving
    case IN_PACKET:
      hadBytes = false;
      b = serial.read();
      while (b >= 0) {
        buffer[bufferPtr++] = b;
        // Buffer full?
        if (bufferPtr >= BUFBLOCKSIZE) {
          // Yes. Something fishy here - bail out!
          // Most probably we will run into an error with this data, but anyway...
          break;
        }
        hadBytes = true;
        b = serial.read();
      }
      // Did we read some?
      if (hadBytes) {
        // Yes, take another turn
        intervalEnd = micros();
        delay(1);
      } else {
        // No. Has a complete interval passed without data?
        lastMicros = micros();
        if (lastMicros - intervalEnd >= interval) {
          // Yes, go processing data
          state = DATA_READ;
        }
      }
      break;
    // DATA_READ: successfully gathered some data. Prepare return object.
    case DATA_READ:

       int len;
       buffer_ = clean_data(buffer, bufferPtr, &len);

      // Did we get a sensible buffer length?
      if (len == 1)
      {
        // Yes. Allocate response object
        for (uint16_t i = 0; i < 9; ++i)
        {
          rv.push_back(buffer_[i]);
        }
        state = FINISHED;
      }

      else
      {
        // Yes. Allocate response object
        for (uint16_t i = 0; i < 7; ++i)
        {
          rv.push_back(buffer_[i]);
        }
        state = FINISHED;
      }
      break;
    // FINISHED: we are done, clean up.
    case FINISHED:
      // CLear serial buffer in case something is left trailing
      // May happen with servers too slow!
      while (serial.available()) serial.read();
      break;
    }
  }
  // Deallocate buffer
  delete[] buffer;

  HEXDUMP_D("Received packet", rv.data(), rv.size());

  return rv;
}

I'm aware this is going against modbus standards, but the problems is I am remotely working on this one and can't arrange for a logic analyzer and employ it with the person hosting the setup.
@KevinDesbonnets  you can test the file for multiple cases and let me know if there any issue.

I tested the file with a simple READ_HOLD_REGISTER function on the modbus device and it's work well, maybe make a pull request of it?
I will test further this patch along with my project thanks you

I checked the code a bit, it's will work with other function than 0x3? I don't think so...
I will this as soon as I can and make some change if necessary

Currently it only works for 03 function code, that too with either 2 or 4 data bytes.
You can modify that in the clean_data function.
Im guessing for making a pull request there needs to support for all the function codes and it might require many more changes pertaining the lenght of the final buffer.

Sorry, I am not going to accept a pull request that will catch a single case only and not tackle the root cause.
The stray byte issue must have special preconditions to happen that the both of you unfortunately seem to have met. Else we would have had more reports alike. So I would rather attempt to find what your projects do have in common.

I read the code a bit further and if you use other function you can have a UB I think
for (int i=0; i<bufferPtr; i++)
    {
        if (buffer1[i]==0x01 && trigger1==0)
        {
            temp1 = buffer1[i];
            trigger1 = 1;
        }

        else if (trigger1 == 1 && count2==0)
        {
            if (buffer1[i-1]==0x01 && buffer1[i]==0x03)
            {
                temp2 = buffer1[i];
            }

            else if(buffer1[i-2]==0x01 && buffer1[i-1]==0x03)
            {

If you use function 0x04 for exemple you will check buffer1[i-2]==0x01 when i == 1

@Miq1 that's fair enough.
The only reason I'm sharing this here is to have a temporary fix of the problem, merging it with the main branch isn't a feasible solution.
@KevinDesbonnets if you have the time and resources, it would be better if you debug the root cause.

Right now I will just use a patch for my case but I will continue a bit and if I find it I will come back to share it :)

Can you leave out the RS485 hardware for a while and use the Serial ports only?
can you connect your respective servers to a PC and Modsim64 or similar to see if the issue is still there?
can you intercept the signal with a scope or logic analyzer as close at the server as possible?

The bytes are shown with the log output immediately upon receipt from Serial, so chances are high that they indeed have been inducted on the Serial line, the RS485 line or are originating from the server itself.

Guys, anything new? Do you have a wiring diagram at hand you can share?

@Miq1 I have asked the person hosting the setup to do the above tasks but it might take a while.
Btw @KevinDesbonnets, which company sensor are you using here? More details would definitely help.
Also which rs485 to ttl converter are you using?
I feel we can close this issue for now as it seems to be not a library issue, we will update here as we have any progress.

Thanks, @Ebrahim1604!
I will leave this open as a question - maybe someone else is having a similar issue and can add some information.

I got another user with nearly the same issue, but the 0x00 bytes coming in separated from the message proper.
I found an interesting report at AVRfreaks that sounds quite like it could point to a cause.
The other user but checked the wiring on the RS485MAX adaptor he is using and according the schematic the RO line should be pulled up as advised - but who knows what the Chinese manufacturer did...
I would ask you to add a pinMode(RX_PIN, INPUT_PULLUP); to your code and see what happens. RX_PIN must be your GPIO you are using for RX of course.

Also….do you have 10k bias resistors on both rx/tx lines? If not, noise on the line might trigger a receiver.

Also….do you have 10k bias resistors on both rx/tx lines? If not, noise on the line might trigger a receiver.

According to the schematics all four RX/TX/DE/RE lines do have the pullups, but you never know... The coincidence of the error scheme is striking.

I always used the schematic as drawn in the old repo:
https://github.com/bertmelis/esp32ModbusRTU
It shows the biasing resistors, terminating resistor and ground loop.
It's only three cheap components more, so I added them.

Closing this now in regards to discussions item #112.


How can I disable slider ?

If I want to disable my slider, is there any props available for that ?
I update my slider with web-socket.
thanks in advance.

I fixed it with return. Style is the same but it is ok.
durationChangeCallback = (duration) => {
     if (this.state.is_started) {
          return; // kind of disable
     }else{
          this.setState({duration});
    }
}

I did it like this:
<Slider
    orientation='horizontal'
    min={1}
    max={5}
    labels={this.state.labels}
    value={this.state.sliderValue}
    onChange={(newValue) => {}}
/>

This library already provides disable props. You need to make following changes in your code.
Make constructor with isDisable state with default false value
constructor(props){
super(props);
this.state={
isDisable:false
}

}

Add a function into onChange callback props
_checkMaximunSliderValue=(value)=>{
 If(value==100){
this.setState({isDisable:true})
}
}

Set this.state.isDisable in disable props
<VerticalSlider
  value={1}
  disabled={this.state.isDisable}
  min={0}
  max={100}
  onChange={(value: number) => {
    this._checkMaximunSliderValue(value);
  }}
  onComplete={(value: number) => {
    console.log("COMPLETE", value);
  }}
  width={50}
  height={300}
  step={1}
  borderRadius={5}
  minimumTrackTintColor={"gray"}
  maximumTrackTintColor={"tomato"}
  showBallIndicator
  ballIndicatorColor={"gray"}
  ballIndicatorTextColor={"white"}
/>;

You can simply add a disabled class as an additional class when you need to disable the slider. Worked for me.
.disabled {
   pointer-events: none;
   opacity: 0.7;
}

<Slider className={isDisabled ? "disabled" : ''}
            min={0}
            max={100}
            value={volume}
            onChange={handleChange}
            onChangeStart={handleChangeStart}
            onChangeComplete={handleChangeComplete}
          />

You can simply add a disabled class as an additional class when you need to disable the slider. Worked for me.
`.disabled {
pointer-events: none;
opacity: 0.7;
}
<Slider className={isDisabled ? "disabled" : ''}
min={0}
max={100}
value={volume}
onChange={handleChange}
onChangeStart={handleChangeStart}
onChangeComplete={handleChangeComplete}
/>`


Use Quay base image

@sdurrheimer
Anything else needed? The pushes happen in the repo's respective ̀circle.yml` files, so it seems to be it.

👍


BabylonJS demo is not compiled with Bridge 16.4

Test project (I was not able to reproduce the issue outside the project)
https://github.com/Retyped/Demos/tree/master/BabylonJsDemo
An exception occurs during compilation
Error: 2017-10-19T19:20:25:047     Error        System.NullReferenceException: Object reference not set to an instance of an object.
   at Bridge.Contract.Rules.Get(IEmitter emitter, IEntity entity)
   at Bridge.Contract.Rules.GetVirtualMemberRules(IEmitter emitter, IEntity entity)
   at Bridge.Contract.Rules.Get(IEmitter emitter, IEntity entity)
   at Bridge.Translator.PreconverterDetecter.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
   at ICSharpCode.NRefactory.CSharp.MethodDeclaration.AcceptVisitor(IAstVisitor visitor)
   at ICSharpCode.NRefactory.CSharp.DepthFirstAstVisitor.VisitChildren(AstNode node)
   at Bridge.Translator.PreconverterDetecter.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
   at ICSharpCode.NRefactory.CSharp.TypeDeclaration.AcceptVisitor(IAstVisitor visitor)
   at ICSharpCode.NRefactory.CSharp.DepthFirstAstVisitor.VisitChildren(AstNode node)
   at ICSharpCode.NRefactory.CSharp.DepthFirstAstVisitor.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
   at ICSharpCode.NRefactory.CSharp.NamespaceDeclaration.AcceptVisitor(IAstVisitor visitor)
   at ICSharpCode.NRefactory.CSharp.DepthFirstAstVisitor.VisitChildren(AstNode node)
   at ICSharpCode.NRefactory.CSharp.DepthFirstAstVisitor.VisitSyntaxTree(SyntaxTree syntaxTree)
   at ICSharpCode.NRefactory.CSharp.SyntaxTree.AcceptVisitor(IAstVisitor visitor)
   at Bridge.Translator.Translator.Preconvert(MemberResolver resolver, IAssemblyInfo config)
   at Bridge.Translator.Translator.Translate()
   at Bridge.Build.BridgeCompilerTask.Execute() (1, 1)

Steps to reproduce:

Clone the project and update Bridge to 16.4.0 using NuGet package manager.
Say 'no' when it asks to replace bridge.json (no new bridge settings are brought from bridge.json during upgrade, so it is safe to be ignored -- and it replaces inherent project settings).
Try to build. Build will fail with the error above.

The minimal test case woud be:

Remove all .cs files from project, leaving only:

SceneProviders/AbstractSceneProvider.cs
SceneProviders/Scene1Provider.cs

change their content to:

AbstractSceneProvider.cs:

using Retyped;

namespace BabylonJsDemo.SceneProviders
{
    public abstract class AbstractSceneProvider
    {
        public abstract int CreateScene(babylon_js.BABYLON.Engine engine);
    }
}

Scene1Provider.cs

using static Retyped.babylon_js.BABYLON;

namespace BabylonJsDemo.SceneProviders
{
    public class Scene1Provider : AbstractSceneProvider
    {
        public override int CreateScene(Engine engine)
        {
            int scene = 4;
            return scene;
        }
    }
}

If you change the references to Engine in both files to int, for example, the error will no longer happen on build.

This fix has been just merged into the branch for version 16.4.1.


Motivation of the IFD order recommandation

(This issue comes from DGIWG Imagery and Gridded Data Panel review of COG Draft Standard - September 2022)
Recommandation 3 ("/rec/rec-class-geotiff/ifd-order") is suggesting to organize data in an certain order when there are several IFD (including mask data IFD) and tiles inside a COG File, in function of the resolutions of the related images.
This is certainly motivated by performance optimization issues, but the standard doesn't explain them. A paragraph that explains the motivation of this recommandation would be helpful.

I copied this from GDAL. I suspected about performance reasons but I do not know exactly why. I have added the following sentence:
"To increase performance, the IFD should be arranged in a particular order expressed in the following recommendation"
If you know more details and you want me to add them in the standard, please supply a text or a reasoning

It is a performance optimization that allows readers to fetch the entire TIFF header (including all IFDs for all subfiles) in a single HTTP GET Range request upon opening the file for the first time.  This reduces the number of round trips to the server required to read a file and improves cache-ability of the TIFF header for repeat requests to the same image.
The TIFF spec is very flexible with how IFDs are positioned, the only requirement is that the last 4 bytes of the IFD point to the byte offset of the next.  So it is totally valid TIFF to have an image where the source image IFD is at the start of the file, the IFD of the first overview is at the end of the file, and the IFD of the second overview is at the middle of the file.  Reading the header of this image in one HTTP request would require downloading the entire file (defeating the purpose of COG to begin with) or in 3 consecutive HTTP requests.

Thanks for the nice text. I have accommodated most of it in the standard draft. I believe we can close this issue now.


llvm: fix #14542

Things done

[ ] Tested using sandboxing (nix-build --option build-use-chroot true or nix.useChroot on NixOS)
Built on platform(s)

[ ] NixOS
[x] OS X
[ ] Linux

[x] Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
[x] Tested execution of all binary files (usually in ./result/bin/)
[x] Fits CONTRIBUTING.md.

Added, I'll try building llvm again in a bit.

Many of the problems have been already addressed by someone else in the meantime, though I don't know if someone truly tested on Darwin.

Closing. I think this work has been largely superceded. Please re-submit if there are still changes that can be integrated.


[5.5][Diagnostics] Diagnose ambiguous solutions with warnings like regular ambiguities

Cherry-pick of https://github.com/apple/swift/pull/38328

Explanation:

Fixes an issue in the solver where it would accept one of the solutions
for an ambiguous expression, which results in a crash later in the pipeline.
If solutions either have no fixes at all or all of them are warnings,
let's use diagnoseAmbiguity to diagnose such cases as-if there are
no fixes at all.

Scope: Ambiguous expressions where some of the solutions have warnings and others do not.

Main Branch PR: https://github.com/apple/swift/pull/38328

Resolves: rdar://79657350

Risk: Low

Reviewed By: @hborla

Testing: Regression tests added to the suite

Resolves: rdar://79657350
(cherry picked from commit d1e12785edf24e697acb0baa28547f1810b0df28)

@swift-ci please clean test

@swift-ci please clean test Linux platform

Build failed
Swift Test OS X Platform
Git Sha - 1760925bbe9f4f89f4e9e214b60b2bb1b2bc29ac

@swift-ci please test macOS platform

@swift-ci please nominate


Something weird is going on, contact admins

Started db1000n using tmux:
tmux new -d "db1000n -enable-self-update"
@Arriven What's wrong here? Worked fine until 10AM or so

the config has changed to include only tcp targets, see #386


Add disabled property to input with styling and condition

I needed this function and noticed that a pull request had been made but things were missing
The style I used is the same as the input border in the normal state, I don't know if that would be okay
I read that "maybe" you should also disable the datepicker, if it is no longer a "maybe" I can add this modification
Regards!

Awesome, thank you!


Timelines is locked for very long time

With write amplification test (https://github.com/zenithdb/zenith/issues/1076)
I constantly get Timed out while waiting for WAL record error after few hours of work.
I suspected that it was caused by locks hold by GC and which prevents other threads to do their work (i.e. sending responses to  walproposer).
And looks like this hypothesis is proved: I got the following messages before timeout happen:
2022-01-05T20:34:30.757113Z  INFO WAL receiver{timeline=36993e17c766caba2767fceb3291f101 tenant=85a9083d299a4d6cb7ba80
8af60da97d}: get_timeline_state wait for timelines lock<PHONE_NUMBER>83s
2022-01-05T20:34:30.757166Z  INFO callmemaybe{timeline=36993e17c766caba2767fceb3291f101 tenant=85a9083d299a4d6cb7ba808
af60da97d}: get_timeline lock<PHONE_NUMBER>42s
connection error: error communicating with the server: Broken pipe (os error 32)

So get_timeline_state waits for 414 seconds for self.timelines lock and definitely walproposer has decided that peer is not alive and drop connection.
I will try to replace std::mutex wtih parking_lot, but may be there is better solution of the problem?

Just replacing std::mutex with parking_lot::mutex in layered_repository.rs doesn't help.
So the problem is not caused by lock starvation...

Finally I produced core dump and find out who is locking timelines mutex.
Actually this problem is well known and I have reported it long time ago: GC is now performed with timelines mutex lock. In my test explicitly GC is called with  checkpoint_before_gc=true which makes times of GC iteration (and so timelines lock) inconceivably long.
But even without GC holding timelines lock for the whole time of GC operation IMHO is not acceptable.

So I think that under the lock we should construct list of timelines to be garbage collected and then release timelines lock and perform GC without holding this lock.

Was this fixed by commit f70a5cad61e756f3185522ff14daf0de9a117ec8?

Yes, this problem is fixed. But it introduce new problems (race conditions) which has to be addressed (#1118). There is one fix which is not yet committed in main: hold checkpoint_cs in GC (to prevent race condition between GC and checkpointer). But I am not sure if it is really good idea.

I think we're all done here, closing.


Initial columns functions

Fixes #9 when finished

We might have to add a hierarchy to the column names because multiple tables contain same column names

Codecov Report

Merging #22 (459b64c) into main (abad9e6) will decrease coverage by 1.78%.
The diff coverage is 92.30%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #22      +/-   ##
==========================================
- Coverage   95.65%   93.87%   -1.78%
==========================================
  Files           4        5       +1
  Lines          23       49      +26
==========================================
+ Hits           22       46      +24
- Misses          1        3       +2

Impacted Files
Coverage Δ

src/genomic_features/_core/columns.py
92.30% <92.30%> (ø)

Check why inner join tb1.left_join(tb2, 'gene_id').execute() returns one column called gene_id while left join returns gene_id_x and gene_id_y

This test needs to be checked: https://github.com/scverse/genomic-features/blob/45d97ac1d586c7c11bfa54afb8e1445ef1e5cab6/tests/test_columns.py#L79


brief description on each release

It would be nice if we can read breif notes about
new release, thanks))

Oh, Thanks, it's helpful!!! When i'd write this one i assumed, https://github.com/olistic/warriorjs/releases
but i'm just novice, and many things isn't obviouse for me at first sight.

Not a problem!


Creating a function to remove structures that should not have been segmented

I noticed that sometimes, nnUNet was having trouble with parts of the anatomy locally similar to the spinal canal. This, regardless of the segmentation of the canal itself which is good, induces the segmentation of things that should not have been segmented, here are some examples :
an eye on whole-spine :

a tissue, anterior to the AL ligament on whole spine :

or even smaller structures on sci-paris :

Since this doesn't really affect the quality of the canal segmentation, but still is a problem, I created a a function using scipy.ndimage "label" function, to isolate the different connecte components from the segmentation.
Since the canal is supposed to be connected, the function sorts those components by size and only keeps the larger and the background, ensuring to have a cleaned segmentation only containing the canal.
Function is here https://github.com/ivadomed/model-canal-seg/blob/abels/postprocessing.py
Or here if you want to test it :
postprocessing.zip

I also noticed that sometimes, correcting images I could missclik with the brush, creating other types of irrgularities, so the function can also be useful for preprocessing segmentations to ensure there aren't any cases like this one :


audit out of memory error handling for libraries

In general we do not handle OOM errors in Envoy and assume that the process should crash. There is a valid concern that libraries might return OOM errors when they are not actually out of memory. We should take a look at cases where this might happen and potentially add more paranoia checking.
cc @htuch

Also, I think that where we do have OOM at the libc level, we should at least throw an exception or crash. It seems we risk entering dangerous territory if we don't. E.g. we reach a near OOM kill scenario, silently ignore an error and leak a buffer with uninitialized data.

For C++ allocations we should throw an exception and will crash.
For C allocations, we obviously won't. Note that from previous experience, libevent seems like it handles OOM conditions, but there are missing cases and it will end up crashing. It's possible this has been fixed in 2.1.

I haven't looked, but optimally we could install some kind of OOM handler in tcmalloc that would handle both C++ and C allocations and then we could definitely crash in all cases.


POST request to URL with GET params

POST request to url http://www.mysite.com?param=1 will send POST request to url http://www.mysite.com.
Should I send pull request? I extend params of proxy_request to ($url, $getData, $postData, $method)  and handle also getData in request.

If you can do the pull request, yes that'd be great. I haven't taken a look at this code for a while so it helps to refresh my memory a little!

600bce4622b6f0b7f356e1c81b568b842ed11ba2


Removing unneeded scripts

Coverage remained the same at 71.208% when pulling b39eee105fa81a0fdb7e1a6794196ec0f42f51de on cleanup into f351c29600b01cb706e4adf5667ac0896d3bc5be on master.

Adding cla: yes label, as the PR author is a googler at the time of this PR was created.


Canvas Size is Miscalculated

When trying to set the game to a width and height of "100" (100%) of parent, the game gets set to 100% of window instead.
index.html

game.js
let game = new Phaser.Game( '100', '100', Phaser.AUTO, '', { preload: preload, create: create, update: update } );

function preload() {
  console.log( document.getElementsByTagName( 'canvas' )[0].width ); // width of window, not canvas parent
}

This post appears to describe the same issue: http://www.html5gamedevs.com/topic/22216-trouble-filling-parent-element-in-dom/
Possibly related to #2458 and #2556

There may be something unexpected going on here, but in the example above no parent has been given, so it defaults to the browser window as the docs say:
The width of your game in game pixels. If given as a string the value must be between 0 and 100 and will be used as the percentage width of the parent container, or the browser window if no parent is given.

Thanks for calling that out. I was thinking width of body because the "Making Your First Game" talks about canvas getting added to the body if no id is specified.
All that said, the behavior is exactly the same if you use a parent element.

  ...scripts...

new Phaser.Game( '100', '100', Phaser.AUTO, 'parent', {...} );

Thank you for taking the time to open this issue. However, official support for Phaser 2 has now ended as we focus on preparing Phaser 3 for beta release. In a bid to keep the project tidy, and avoid confusion, we are closing all v2 related issues.
This does not mean your issue won't be looked-at. In November 2016 the Phaser CE (Community Edition) project began. The aim of Phaser CE was to allow the community to continue v2 development. Since then it has gained significant traction, with many updates and releases.
If you are still interested in having your issue investigated we strongly recommend testing the latest Phaser CE release. And only if the problem persists, opening an issue on the Phaser CE repo.


Use base template for views OUTSIDE of BaseView?

I am currently using Flask-admin for about 85% of my application which centers around manipulating database models.
However, for the remaining 15%, I am sticking to the style recommended on the flask website.
Now for these view functions if the layout file tries to extend the Flask-admin base template via {% extends "admin/master.html" %} I am getting a UndefinedError: 'admin_base_template' is undefined error.
I understand this is caused by the fact that I am not using ModelView or BaseView.
What are my options here?

Convert ALL my view functions to using BaseView from flask-admin? I don't know if I want to do that.
Maintain a separate layout file just for that 15% of view functions?

There must be a better way, right?

from flask import Flask, render_template
from flask_admin import Admin, base
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = 'your_secret_key_here'

db = SQLAlchemy(app)
admin = Admin(app, name='Admin Panel', template_mode='bootstrap3')

# Define your Flask-Admin models/views
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)

admin.add_view(ModelView(User, db.session))

# Flask-Admin template context processor for non-Flask-Admin views
@app.context_processor
def admin_context_processor():
    return dict(
        admin_base_template=base.template,
        admin_view=base._get_current_admin(),
        h=admin.helpers,
        config=admin.config,
        get_url=base.get_url
    )

# Non-Flask-Admin view function
@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    db.create_all()
    app.run(debug=True)


Remove some meaningless jms properties

Backport #32456 to the main branch.

API change check
APIView has identified API level changes in this PR and created following API reviews.
spring-cloud-azure-autoconfigure


Evaluation Metric

There exist small mistakes in the original evaluation source code of NOCS. I recommend changing to revised metrics (https://github.com/swords123/SSC-6D#note). DPDN code also has the same issues.
https://github.com/CVMI-Lab/IST-Net/blob/169e1cf7ee2d2a56fdeee4a0d755b85df2330e7a/utils/evaluation_utils.py#L128-L131
        # new
        bbox_1_max = np.amax(bbox_3d_1, axis=1)
        bbox_1_min = np.amin(bbox_3d_1, axis=1)
        bbox_2_max = np.amax(bbox_3d_2, axis=1)
        bbox_2_min = np.amin(bbox_3d_2, axis=1)

Thanks for your remind, I will update the code in the next few days!

Thanks :)


some problem about Image preview within tmux

What system are you running Yazi on?
Linux X11
What terminal are you running Yazi in?
bash
Yazi version
yazi 0.1.5 (3fcc201 2024-01-05)
Did you try the latest main branch to see if the problem has already been fixed?
Tried, but the problem is still present
Describe the bug
To enable Yazi's image preview to work correctly in tmux, add the following 3 options to your tmux.conf:
set -g allow-passthrough on
set -ga update-environment TERM
set -ga update-environment TERM_PROGRAM
but when I follow this step and restart tmux, I reported an error when opening tmux.
.tmux.conf:5: invalid option: allow-passthrough
Expected Behavior
null
To Reproduce
modify ~/.tmux.conf.
Configuration
No response
Anything else?
No response

In normal mode, the new configuration can be seen, but there is no change in tmux and an error is also reported

What's your tmux version? And please paste your full ~/.tmux.conf content here

this is my ~/.tmux.conf:
set -g default-terminal "xterm-256color"
#set -g default-terminal "screen-256color"
set -g renumber-windows
#set -g allow-passthrough on
set -ga update-environment TERM
set -ga update-environment TERM_PROGRAM
run-shell /home/tt/tmux_config/tmux-onedark-theme.tmux
and tmux -V is tmux 3.0a

tmux 3.0a does not support passthrough mode, which is an option introduced in tmux 3.3, see https://raw.githubusercontent.com/tmux/tmux/3.3/CHANGES:
CHANGES FROM 3.2a TO 3.3
...
* Add an option (default off) to control the passthrough escape sequence.

Please upgrade your tmux to the latest version.


Moved getUsedLibraries() fun to viewModel

Definitely a good change 👍
Looks like ktlint check is not passing (wildcard imports), but don't worry, I will fix it after merge
Thanks! 😄


Add test file for IMDB module

Note

Test all the methods of the imdb module and add a test file for the same.
Add test file in directory src/test.
Check the codechef_test.py file as a reference to get an idea about structuring the code.
Use unittest only.

Hi @nikhil25803, just to be sure you want unit tests for this file. Right?

@nikhil25803  I encountered some errors while running the test case, please look at the issue created.

Hey @Vishal-Padia, will check your bug PR only. And guys, @Vishal-Padia and Vishal, do not start working on an issue before getting assigned, it is not an open-source good practice, to assign this issue to @burhanharoon.

okay, cool!


⚠ Bofrost.de has degraded performance

In 816b056, Bofrost.de (https://www.bofrost.de) experienced degraded performance:

HTTP code: 200
Response time: 1098 ms

Resolved: Bofrost.de performance has improved in 1da013e after 6 minutes.


Buffer lock/release fixes

Fixes a few edge cases with buffer locking and releasing. Needs testing.
Fixes #7091
Possibly impacted:

direct scanout
cursors

Untested:

xwayland

also @UjinT34 looking at the nvidia dumb copy this might break this, but I am unsure. Care to test?

I need some testing, rocking this rn and all seems well

Cursor dumb copy crashes to tty when I hover over a client side cursor window. Trying to get the backtrace only gives
#0  0x00005d287978b64e in Hyprutils::Memory::CWeakPointer<IHLBuffer>::lock (this=0x0) at /usr/include/hyprutils/memory/WeakPtr.hpp:122
#1  0x00005d2879822932 in CPointerManager::renderHWCursorBuffer (this=0x5d28b4d2aa80, state=..., texture=...) at /home/ming/documents/git/hyprland/src/managers/PointerManager.cpp:433
        PDUMB = {p_ = 0x5d28b4d9fb00}

Direct scanout works (intel). Xwayland works.

Guess I'll put it here too:

Black borders appeared on the edge of my monitor
XCursor shapes are wrong again

dumb copy is a bit complicated here, I'll see what I can do... the way it's been working right now was technically wrong

@Agent00Ming pls test dumb

crashes on start bt.txt

can you compile hyprutils with asan and get a trace?

dunno if I did it right asan.txt

now?

no, it still crashes on start

why does it not on my end :/ trace still the same?

slightly different asan-1.txt

try now

woo cursed fixed

try no

hmm, cursor is invisible in blender but appears normally elsewhere.
hyprlandd.log

try n

crash on client side cursor bt.txt

yeeeaaa this is a problem ugh

architecture kinda sucks in this scenario

it works now but direct scanout is left and entered for every frame in minecraft (xwayland) and it causes the same for the very first frame that the cursor hovers over vkcube-wayland in direct scanout

can you bisect that one to make sure it's not something that should be fixed here

first bad commit: [682865632fe986d179ca07e45ae89e65b8058b33] xwayland: fix high cpu idle usage
bisect_xwl_ds.log

ok its unrelated to this then, will merge tomorrow. Thanks, you can open another issue I guess

Can confirm this PR fixes #7103 for me. However it seems to introduce a crash when closing Minecraft (only when running under gamescope) which did not happen before. This could be an unrelated crash caused by external changes though.
hyprlandCrashReport127343.txt

get a debug stacktrace please

I'll wait a few hours more, otherwise I am merging and that crash can be opened as an issue, if anyone can repro

I'll wait a few hours more, otherwise I am merging and that crash can be opened as an issue, if anyone can repro

compiling atm, il fire up my trusty bg3, and various xwl things see if i can reproduce. heh

I'll wait a few hours more, otherwise I am merging and that crash can be opened as an issue, if anyone can repro

I'll wait a few hours more, otherwise I am merging and that crash can be opened as an issue, if anyone can repro

gamescope -f vkcube
#0  0x00007ffff70a159c in pthread_kill () at /usr/lib64/libc.so.6
#1  0x00007ffff704449a in raise () at /usr/lib64/libc.so.6
#2  0x00007ffff70284ed in abort () at /usr/lib64/libc.so.6
#3  0x0000555555691f73 in handleUnrecoverableSignal (sig=11) at ../hyprland-9999/src/Compositor.cpp:72
#4  0x00007ffff7044530 in <signal handler called> () at /usr/lib64/libc.so.6
#5  std::vector<Hyprutils::Memory::CWeakPointer<CWLSubsurfaceResource>, std::allocator<Hyprutils::Memory::CWeakPointer<CWLSubsurfaceResource> > >::size (this=0x348) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/vector:113
#6  std::erase_if<Hyprutils::Memory::CWeakPointer<CWLSubsurfaceResource>, std::allocator<Hyprutils::Memory::CWeakPointer<CWLSubsurfaceResource> >, CWLSurfaceResource::bfHelper(std::vector<Hyprutils::Memory::CSharedPointer<CWLSurfaceResource> >, std::function<void(Hyprutils::Memory::CSharedPointer<CWLSurfaceResource>, const Hyprutils::Math::Vector2D&, void*)>, void*)::<lambda(const auto:56&)> > (__cont=<error reading variable: Cannot access memory at address 0x350>, __pred=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/vector:117
#7  CWLSurfaceResource::bfHelper (this=this@entry=0x555556c47120, nodes=std::vector of length 6, capacity 6 = {...}, fn=..., data=data@entry=0x7fffffffcdf0) at ../hyprland-9999/src/protocols/core/Compositor.cpp:261
#8  0x00005555558ec5aa in CWLSurfaceResource::bfHelper (this=this@entry=0x555556c47120, nodes=std::vector of length 1, capacity 1 = {...}, fn=..., data=data@entry=0x7fffffffcdf0) at ../hyprland-9999/src/protocols/core/Compositor.cpp:294
#9  0x00005555558ec861 in CWLSurfaceResource::breadthfirst (this=0x555556c47120, fn=..., data=0x7fffffffcdf0) at ../hyprland-9999/src/protocols/core/Compositor.cpp:300
#10 0x000055555593898a in CHyprRenderer::renderWindow (this=<optimized out>, pWindow=..., pMonitor=0x5555568e50d0, time=<optimized out>, decorate=true, mode=RENDER_PASS_ALL, ignorePosition=false, ignoreAllGeometry=false) at ../hyprland-9999/src/render/Renderer.cpp:619
#11 0x00005555559305c2 in CHyprOpenGLImpl::makeWindowSnapshot (this=<optimized out>, pWindow=...) at ../hyprland-9999/src/render/OpenGL.cpp:2327
#12 0x000055555576e5ef in Events::listener_unmapWindow (owner=<optimized out>, data=<optimized out>) at ../hyprland-9999/src/events/Windows.cpp:611
#13 0x0000555555753daa in operator() (__closure=0x555556a6c240, d=std::any [no contained value]) at ../hyprland-9999/src/desktop/Window.cpp:68
#14 std::__invoke_impl<void, CWindow::CWindow(Hyprutils::Memory::CSharedPointer<CXDGSurfaceResource>)::<lambda(std::any)>&, std::any> (__f=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/invoke.h:61
#15 std::__invoke_r<void, CWindow::CWindow(Hyprutils::Memory::CSharedPointer<CXDGSurfaceResource>)::<lambda(std::any)>&, std::any> (__fn=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/invoke.h:111
#16 std::_Function_handler<void(std::any), CWindow::CWindow(Hyprutils::Memory::CSharedPointer<CXDGSurfaceResource>)::<lambda(std::any)> >::_M_invoke(const std::_Any_data &, std::any &&) (__functor=..., __args#0=<optimized out>)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/std_function.h:290
#17 0x00007ffff7c56fcc in Hyprutils::Signal::CSignalListener::emit(std::any) () at /usr/lib64/libhyprutils.so.1
#18 0x00007ffff7c5753e in Hyprutils::Signal::CSignal::emit(std::any) () at /usr/lib64/libhyprutils.so.1
#19 0x00005555558dc829 in operator() (d=std::any [no contained value], __closure=0x555556af70d0) at ../hyprland-9999/src/protocols/XDGShell.cpp:338
#20 std::__invoke_impl<void, CXDGSurfaceResource::CXDGSurfaceResource(Hyprutils::Memory::CSharedPointer<CXdgSurface>, Hyprutils::Memory::CSharedPointer<CXDGWMBase>, Hyprutils::Memory::CSharedPointer<CWLSurfaceResource>)::<lambda(std::any)>&, std::any> (__f=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/invoke.h:61
#21 std::__invoke_r<void, CXDGSurfaceResource::CXDGSurfaceResource(Hyprutils::Memory::CSharedPointer<CXdgSurface>, Hyprutils::Memory::CSharedPointer<CXDGWMBase>, Hyprutils::Memory::CSharedPointer<CWLSurfaceResource>)::<lambda(std::any)>&, std::any> (__fn=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/invoke.h:111
#22 std::_Function_handler<void(std::any), CXDGSurfaceResource::CXDGSurfaceResource(Hyprutils::Memory::CSharedPointer<CXdgSurface>, Hyprutils::Memory::CSharedPointer<CXDGWMBase>, Hyprutils::Memory::CSharedPointer<CWLSurfaceResource>)::<lambda(std::any)> >::_M_invoke(const std::_Any_data &, std::any &&) (__functor=..., __args#0=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/std_function.h:290
#23 0x00007ffff7c56fcc in Hyprutils::Signal::CSignalListener::emit(std::any) () at /usr/lib64/libhyprutils.so.1
#24 0x00007ffff7c5753e in Hyprutils::Signal::CSignal::emit(std::any) () at /usr/lib64/libhyprutils.so.1
#25 0x00005555558e977a in CWLSurfaceResource::destroy (this=0x555556c47120) at ../hyprland-9999/src/protocols/core/Compositor.cpp:159
#26 0x0000555555973031 in std::function<void(CWlSurface*)>::operator() (this=0x555556c470c0, __args#0=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/std_function.h:591
#27 CWlSurface::onDestroyCalled (this=0x555556c46f60) at protocols/wayland.cpp:2031
#28 _CWlSurface__DestroyListener (l=<optimized out>, d=<optimized out>) at protocols/wayland.cpp:1853
#29 0x00007ffff7e610d4 in ??? () at /usr/lib64/libwayland-server.so.0
#30 0x00007ffff7e651c3 in wl_client_destroy () at /usr/lib64/libwayland-server.so.0
#31 0x00007ffff7e655d8 in ??? () at /usr/lib64/libwayland-server.so.0
#32 0x00007ffff7e646b3 in ??? () at /usr/lib64/libwayland-server.so.0
#33 0x00007ffff7e65509 in wl_display_run () at /usr/lib64/libwayland-server.so.0
#34 0x00005555557fc6f5 in CEventLoopManager::enterLoop (this=0x555555bfe290) at ../hyprland-9999/src/managers/eventLoop/EventLoopManager.cpp:52
#35 0x000055555564c77e in main (argc=<optimized out>, argv=<optimized out>) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/unique_ptr.h:193

thanks :)

try now

try now

yeah works now

top, merging then, thanks!


empty_value change does not compile on Mac

The empty_value change 438d74c7fb85c604d9d8bec1c0a2c23aabd8710a fails to compile on Mac while including boost/url/src.hpp
(I'm using boost 1.80.0 b1)
In file included from .../XXX.cpp:5:
In file included from .../boost_url_source/include/boost/url/src.hpp:39:
In file included from .../boost_url_source/include/boost/url/detail/impl/segments_encoded_iterator_impl.ipp:15:
.../boost_url_source/include/boost/url/rfc/detail/path_rules.hpp:88:16: error: constexpr variable cannot have non-literal type 'const boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>'
constexpr auto slash_segment_rule =
^
.../boost_url_source/include/boost/url/grammar/tuple_rule.hpp:90:7: note: 'sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>' is not literal because it has base class 'empty_value<detail::tuple<squelch_rule_t<ch_delim_rule>, pct_encoded_rule_t<charset_ref<lut_chars>>>>' of non-literal type
: empty_value<
^~~~~~~~~~~~
In file included from .../XXX.cpp:5:
In file included from .../boost_url_source/include/boost/url/src.hpp:39:
In file included from .../boost_url_source/include/boost/url/detail/impl/segments_encoded_iterator_impl.ipp:15:
.../boost_url_source/include/boost/url/rfc/detail/path_rules.hpp:132:16: error: constexpr variable cannot have non-literal type 'const boost::urls::grammar::range_rule_t<boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>>'
constexpr auto path_abempty_rule =
^
.../boost_url_source/include/boost/url/grammar/range_rule.hpp:330:13: note: 'range_rule_t<boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>>' is not literal because it has data member 'next_' of non-literal type 'const boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>'
R const next_;
^
In file included from .../XXX.cpp:5:
In file included from .../boost_url_source/include/boost/url/src.hpp:61:
In file included from .../boost_url_source/include/boost/url/impl/url_base.ipp:24:
.../boost_url_source/include/boost/url/rfc/detail/fragment_rule.hpp:50:16: error: constexpr variable cannot have non-literal type 'const boost::urls::grammar::optional_rule_t<boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>>'
constexpr auto fragment_part_rule =
^
.../boost_url_source/include/boost/url/grammar/optional_rule.hpp:90:10: note: 'optional_rule_t<boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>>' is not literal because it has data member 'r_' of non-literal type 'boost::urls::grammar::sequence_rule_t<boost::urls::grammar::detail::squelch_rule_tboost::urls::grammar::ch_delim_rule, boost::urls::pct_encoded_rule_t<boost::urls::grammar::detail::charset_refboost::urls::grammar::lut_chars>>'
Rule r_;
^
3 errors generated.

Both Boost.Core and this project run CI tests on Mac, so you have to be more specific than that. Which Mac, which compiler, which compiler version, what compilation flags were in effect?

You need the latest Boost.Core from the master branch:
https://github.com/boostorg/core/commits/master

I missed the boost 1.80.0 release, all ok with that version.