Skip to content

Set timeout of communication on the fly #62

@vsaljooghi

Description

@vsaljooghi

Dear Simon,

For my use case, I need a Modbus library API that allows temporarily modifying of bus communication timeout.

Background
I have many devices from different manufacturers connected to the same bus. The communication timeout is normally selected based on the maximum response time among all devices (taken from each device’s datasheet).
It is important to keep this timeout as small as possible—if a device becomes defective or unresponsive, a short timeout prevents it from delaying the entire bus.

Why a temporary timeout change is needed
Firmware updates behave differently from normal Modbus operations(accessing registers of device). During an update, the device receives the firmware image in many chunks. Its response time is significantly slower because it has to write to the MCU flash memory and verify the written data.

For example:

  • Normal sensor-read commands complete in < 400 ms
  • Each firmware-update chunk may require a timeout of ~1400 ms

Because of this, I need the Modbus library to support temporarily increasing the timeout before starting a firmware update, and then restoring the original timeout once the update is complete.

I did below changes to add SetTimeout() to the modbus library API:

In client.go file:

func (mc *ModbusClient) SetTimeout(newTimeout time.Duration) (oldTimeout time.Duration) {
	mc.lock.Lock()
	defer mc.lock.Unlock()

	if mc.transport != nil {
		return mc.transport.SetTimeout(newTimeout)
	}

	return
}

In transport.go:

type transport interface {
	Close() error
	ExecuteRequest(*pdu) (*pdu, error)
	ReadRequest() (*pdu, error)
	WriteResponse(*pdu) error
	SetTimeout(time.Duration) time.Duration
}

In rtu_transport.go:

func (rt *rtuTransport) SetTimeout(newTimeout time.Duration) (oldTimeout time.Duration) {
	oldTimeout = rt.timeout
	rt.timeout = newTimeout

	return
}

In tcp_transport.go:

func (tt *tcpTransport) SetTimeout(newTimeout time.Duration) (oldTimeout time.Duration) {
	oldTimeout = tt.timeout
	tt.timeout = newTimeout

	return
}

Usage:

oldTimeout := mbusClient.SetTimeout(1400 * time.Millisecond)
defer mbusClient.SetTimeout(oldTimeout)

Could you please confirm that I haven’t overlooked anything?

MfG,
Vahid Saljooghi

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