aldas / modbus-tcp-client

PHP client for Modbus TCP and Modbus RTU over TCP (can be used for serial)
Apache License 2.0
192 stars 55 forks source link

Call to undefined method ReadCoilsResponse::getWordAt() / ReadInputDiscretesResponse::getWordAt() #37

Closed harli91 closed 5 years ago

harli91 commented 5 years ago

When i try to get some values using FC1 or FC2 and allFromArray() function i get the following errors at parsing

Call to undefined method ModbusTcpClient\Packet\ModbusFunction\ReadCoilsResponse::getWordAt()

Call to undefined method ModbusTcpClient\Packet\ModbusFunction\ReadInputDiscretesResponse::getWordAt()

aldas commented 5 years ago

@harli91 could you paste sample of you code?

allFromArray is method of ReadRegistersBuilder and WriteRegistersBuilder and those classes are used to make FC3/FC4 requests.

Are you creating your own instance of ReadRegistersBuilder instance with default constructor? ala

$x = new ReadRegistersBuilder(ReadCoilsRequest::class, $uri, $unitId);

actually ReadRegistersBuilder Registers in name says that it mean to for register type requests but this does not mean that we could not have ReadCoilsBuilder like class what does what you need.

anyway, could you show me your code/usecase and maybe I can help you

harli91 commented 5 years ago

As you sad i build the request using an new instance of ReadRegistersBuilder

$fncArray = [
        "3"=>"newReadHoldingRegisters",
        "4"=>"newReadInputRegisters",
        "2" => ModbusTcpClient\Packet\ModbusFunction\ReadInputDiscretesRequest::class,
                "1" => ModbusTcpClient\Packet\ModbusFunction\ReadCoilsRequest::class
        ];
        if(in_array($fnc,["1","2"])) {
            $rq = new ModbusTcpClient\Composer\Read\ReadRegistersBuilder($fncArray[$fnc]);
        } else {
            $rq = ModbusTcpClient\Composer\Read\ReadRegistersBuilder::{$fncArray[$fnc]}();
        }
        $rq = $rq->allFromArray($data)

and when i parse using

$parsedResponse = $this->request->parse($data); i get the errors

The errors i think originate ModbusTcpClient\Composer\Read\ReadAddress, function extractInternal

aldas commented 5 years ago

Coils/InputDiscrete (fc1/fc2) and (Holding/Input)Register (fc3/fc4) or 2 different things. Coil is boolean - it is 1 (on) or 0 (off) but Register (aka Word) is 2 bytes of any data - what data type it is your to decide - it can be readout temperature sensor.

What ReadRegistersBuilder does, it helps you to retrieve data in a data type that you need. It does not make sense for me to fetch array of bits (boolean) and combine 16 coils to get 1 int16 value.

could you print_r maybe value of $data for line $rq = $rq->allFromArray($data) I would like to see what aadresses and data types are this code fetching with fc1/fc2. Are you fetching only bit values when requesting fc1/fc2?

harli91 commented 5 years ago

if i use bit or byte i get a similar error in the same extractInternal function in classes ModbusTcpClient\Composer\Address\BitReadAddress(ByteReadAddress)

here is a print_r of a bit request

Array
(
    [0] => ModbusTcpClient\Composer\Read\ReadRequest Object
        (
            [uri:ModbusTcpClient\Composer\Read\ReadRequest:private] => tcp://192.168.1.103:502
            [addresses:ModbusTcpClient\Composer\Read\ReadRequest:private] => Array
                (
                    [0] => ModbusTcpClient\Composer\Read\BitReadAddress Object
                        (
                            [bit:ModbusTcpClient\Composer\Read\BitReadAddress:private] => 0
                            [name:ModbusTcpClient\Composer\Read\ReadAddress:private] => test
                            [callback:protected] => 
                            [errorCallback:ModbusTcpClient\Composer\Read\ReadAddress:private] => 
                            [address:protected] => 5
                            [type:protected] => bit
                        )

                )

            [request:ModbusTcpClient\Composer\Read\ReadRequest:private] => ModbusTcpClient\Packet\ModbusFunction\ReadCoilsRequest Object
                (
                    [quantity:ModbusTcpClient\Packet\ModbusFunction\ReadCoilsRequest:private] => 1
                    [startAddress:ModbusTcpClient\Packet\ProtocolDataUnitRequest:private] => 5
                    [header:ModbusTcpClient\Packet\ProtocolDataUnit:private] => ModbusTcpClient\Packet\ModbusApplicationHeader Object
                        (
                            [transactionId:ModbusTcpClient\Packet\ModbusApplicationHeader:private] => 56714
                            [length:ModbusTcpClient\Packet\ModbusApplicationHeader:private] => 6
                            [unitId:ModbusTcpClient\Packet\ModbusApplicationHeader:private] => 0
                        )

                )

        )

)
aldas commented 5 years ago

still ReadRegistersBuilder is not meant for FC1/FC2 and should not be used with FC1/FC2 as it only supports registers and not coils as addresses.

I created #38 to deal with request builder for modbus coils (fc1/fc2)