Class: RubyZmqFramework::CanBridge

Inherits:
Object
  • Object
show all
Includes:
FrameworkModule
Defined in:
lib/ruby_zmq_framework/can_bridge.rb

Overview

Reads raw frames off a real SocketCAN interface (can0, vcan0, ...) and rebroadcasts each one onto the ZeroMQ bus. Pure producer: it has no interest in bus traffic, so handle_message is a no-op that only exists to satisfy FrameworkModule's contract.

Talks to the kernel directly via Ruby's built-in Socket + a couple of raw ioctl/struct calls (see linux/can.h, linux/sockios.h) rather than a third-party gem, since no maintained "socketcan" gem is published on RubyGems.

Classic CAN only: reads assume the 16-byte struct can_frame. That is safe even on an FD-enabled interface — the kernel only delivers 72-byte canfd_frames to sockets that opt in via CAN_RAW_FD_FRAMES, which this one never does — but it means FD traffic is invisible here.

Constant Summary collapse

CAN_RAW =
1
SIOCGIFINDEX =
0x8933
FRAME_SIZE =

sizeof(struct can_frame): 4(id) + 1(len) + 3(pad) + 8(data)

16
CAN_EFF_FLAG =
0x80000000
CAN_EFF_MASK =
0x1FFFFFFF
CAN_SFF_MASK =
0x7FF

Constants included from FrameworkModule

FrameworkModule::HEARTBEAT_INTERVAL

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FrameworkModule

#broadcast, included, #node_name, #stop_heartbeat

Constructor Details

#initialize(bus, interface:, topic: :can_frame) ⇒ CanBridge

Returns a new instance of CanBridge.



36
37
38
39
40
41
42
# File 'lib/ruby_zmq_framework/can_bridge.rb', line 36

def initialize(bus, interface:, topic: :can_frame)
  @bus = bus
  @topic = topic
  @socket = open_can_socket(interface)
  @running = true
  start_reader
end

Class Method Details

.parse_frame(raw) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/ruby_zmq_framework/can_bridge.rb', line 28

def self.parse_frame(raw)
  id_raw, len = raw.unpack('L< C')
  extended = (id_raw & CAN_EFF_FLAG) != 0
  can_id = id_raw & (extended ? CAN_EFF_MASK : CAN_SFF_MASK)

  { id: can_id, extended: extended, dlc: len, data: raw[8, len].bytes }
end

Instance Method Details

#closeObject

Stops the whole node: heartbeat, reader thread, CAN socket. Closing the socket from here is what interrupts the reader's blocking read.



48
49
50
51
52
53
54
55
56
# File 'lib/ruby_zmq_framework/can_bridge.rb', line 48

def close
  return unless @running

  @running = false
  stop_heartbeat
  @socket.close unless @socket.closed?
  @reader.join(2)
  nil
end

#handle_message(topic, payload) ⇒ Object



44
# File 'lib/ruby_zmq_framework/can_bridge.rb', line 44

def handle_message(topic, payload); end