github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/pkg/socketcan/transmitter.go (about)

     1  package socketcan
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  
     8  	"github.com/blueinnovationsgroup/can-go"
     9  )
    10  
    11  type TransmitterOption func(*transmitterOpts)
    12  
    13  type transmitterOpts struct {
    14  	frameInterceptor FrameInterceptor
    15  }
    16  
    17  // Transmitter transmits CAN frames.
    18  type Transmitter struct {
    19  	opts transmitterOpts
    20  	conn net.Conn
    21  }
    22  
    23  // NewTransmitter creates a new transmitter that transmits CAN frames to the provided io.Writer.
    24  func NewTransmitter(conn net.Conn, opt ...TransmitterOption) *Transmitter {
    25  	opts := transmitterOpts{}
    26  	for _, f := range opt {
    27  		f(&opts)
    28  	}
    29  	return &Transmitter{
    30  		conn: conn,
    31  		opts: opts,
    32  	}
    33  }
    34  
    35  // TransmitMessage transmits a CAN message.
    36  func (t *Transmitter) TransmitMessage(ctx context.Context, m can.Message) error {
    37  	f, err := m.MarshalFrame()
    38  	if err != nil {
    39  		return fmt.Errorf("transmit message: %w", err)
    40  	}
    41  	return t.TransmitFrame(ctx, f)
    42  }
    43  
    44  // TransmitFrame transmits a CAN frame.
    45  func (t *Transmitter) TransmitFrame(ctx context.Context, f can.Frame) error {
    46  	var scf frame
    47  	scf.encodeFrame(f)
    48  	data := make([]byte, lengthOfFrame)
    49  	scf.marshalBinary(data)
    50  	if deadline, ok := ctx.Deadline(); ok {
    51  		if err := t.conn.SetWriteDeadline(deadline); err != nil {
    52  			return fmt.Errorf("transmit frame: %w", err)
    53  		}
    54  	}
    55  	if _, err := t.conn.Write(data); err != nil {
    56  		return fmt.Errorf("transmit frame: %w", err)
    57  	}
    58  	if t.opts.frameInterceptor != nil {
    59  		t.opts.frameInterceptor(f)
    60  	}
    61  	return nil
    62  }
    63  
    64  // Close the transmitter's underlying connection.
    65  func (t *Transmitter) Close() error {
    66  	return t.conn.Close()
    67  }
    68  
    69  // TransmitterFrameInterceptor returns a TransmitterOption that sets the FrameInterceptor for the
    70  // transmitter. Only one frame interceptor can be installed.
    71  func TransmitterFrameInterceptor(i FrameInterceptor) TransmitterOption {
    72  	return func(o *transmitterOpts) {
    73  		o.frameInterceptor = i
    74  	}
    75  }