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 }