Skip to content

ReadCoils endianness  #47

@arkadiiemelianov-brt

Description

@arkadiiemelianov-brt

Hi!

I'm currently experimenting with Modbus RTU Relay 32ch connected to the ethernet via RS485_TO_ETH.
I'm using rtuovertcp:// scheme to connect and send commands to the RTU Relay.

Your library works perfectly controlling Relays/Coils, but I have a problems when reading status of the relays using ReadCoils API call. It looks like either library uses wrong endianness when parsing ReadCoils response or my hardware uses wrong endianness when reporting the status of the coils.

Here is the Wireshark captures (I'm setting coil number 12 on, zero-based 11, and the requesting the status):
write_coil_request
write_coil_response
readcoils_response

The TCP steam is following:

0105000bff00fdf8       # write coil with address 11
0105000bff00fdf8       # write coil response
0101000000203dd2       # read coils request
01010400000800fc11     # read coils response

Decoded, the response looks like this:
ReadCoils response (the bit number 19 is set):

[]bool{
    false, false, false, false, false, false, false, false,
    false, false, false, false, false, false, false, false,
    false, false, false, true, false, false, false, false,
    false, false, false, false, false, false, false, false
}

But effectively response should look like this:
ReadCoils corrected (the bit number 12 is set):

[]bool{
    false, false, false, false, false, false, false, false,
    false, false, false, true, false, false, false, false,
    false, false, false, false, false, false, false, false,
    false, false, false, false, false, false, false, false
}

For correction the response of ReadCoils API response I'm currently using following:

func bitsToCoils(bits []bool) []bool {
	val := bitsToUint32(bits)
	buf := make([]byte, 4)
	binary.LittleEndian.PutUint32(buf, val)
	res := binary.BigEndian.Uint32(buf)
	return uint32ToBits(res)
}

func bitsToUint32(bits []bool) uint32 {
	var r uint32 = 0
	for i, bit := range bits {
		if bit {
			r |= 1 << i
		}
	}
	return r
}

func uint32ToBits(bits uint32) []bool {
	var r []bool
	for i := 0; i < 32; i++ {
		r = append(r, bits&(1<<i) > 0)
	}
	return r
}

Shall library take endianness into account when parsing ReadCoil status or it's just my hardware firmware is broken?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions