can_messenger 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -15
- data/lib/can_messenger/messenger.rb +32 -14
- data/lib/can_messenger/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67c064d4b8899c012642e83b9c348cf72da13eb136bc81283a2acb7116e79897
|
4
|
+
data.tar.gz: ddb8c322325800be6b03813510e1831348e724967e4f05daa9ac0c2b5b32dad3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d248a72be8fb4b407fa4b79f42fc291658b39340db84c255440cd33b465c02ca7a2d6bf9274a1b52cae8b4cb3b4890d0d2562238040d2365649c1d7d7e0300e
|
7
|
+
data.tar.gz: 7749d6a7544e43db00dfec4a44a967362b449b78bb657da2f7e3afefc04956a466a9348c9414f05c2b72669858e8cecc27f8ac0b32fa2d6c8b58cbaca492e041
|
data/README.md
CHANGED
@@ -11,18 +11,6 @@
|
|
11
11
|
|
12
12
|
## Installation
|
13
13
|
|
14
|
-
Ensure you have `SocketCAN` available on your system. Typically on Linux (e.g., Debian/Ubuntu), you install SocketCAN support with:
|
15
|
-
|
16
|
-
```bash
|
17
|
-
sudo apt-get install net-tools iproute2
|
18
|
-
```
|
19
|
-
|
20
|
-
Then bring up your CAN interface (e.g., `can0`) using `ip` commands or a tool like `can-utils` (though this gem no longer depends on `cansend`):
|
21
|
-
|
22
|
-
```bash
|
23
|
-
sudo ip link set can0 up type can bitrate 500000
|
24
|
-
```
|
25
|
-
|
26
14
|
To install `can_messenger`, add it to your application's Gemfile:
|
27
15
|
|
28
16
|
```ruby
|
@@ -63,13 +51,19 @@ messenger.send_can_message(id: 0x123, data: [0xDE, 0xAD, 0xBE, 0xEF])
|
|
63
51
|
|
64
52
|
> **Note:** Under the hood, the gem now writes CAN frames to a raw socket instead of calling `cansend`. No external dependencies are required beyond raw-socket permissions.
|
65
53
|
|
66
|
-
|
54
|
+
If you need to send an extended CAN frame (29-bit ID), set extended_id: true. The gem then sets the Extended Frame Format (EFF) bit automatically:### Receiving CAN Messages
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
messenger.send_can_message(id: 0x123456, data: [0x01, 0x02, 0x03], extended_id: true)
|
58
|
+
```
|
59
|
+
|
60
|
+
### Listen to CAN Messages
|
67
61
|
|
68
62
|
To listen for incoming messages, set up a listener:
|
69
63
|
|
70
64
|
```ruby
|
71
|
-
messenger.start_listening do |
|
72
|
-
puts "Received
|
65
|
+
messenger.start_listening do |msg|
|
66
|
+
puts "Received ID=0x#{msg[:id].to_s(16)}, Extended=#{msg[:extended]}, Data=#{msg[:data]}"
|
73
67
|
end
|
74
68
|
```
|
75
69
|
|
@@ -15,7 +15,7 @@ module CanMessenger
|
|
15
15
|
# messenger.start_listening do |message|
|
16
16
|
# puts "Received: ID=#{message[:id]}, Data=#{message[:data].map { |b| '0x%02X' % b }}"
|
17
17
|
# end
|
18
|
-
class Messenger
|
18
|
+
class Messenger # rubocop:disable Metrics/ClassLength
|
19
19
|
FRAME_SIZE = 16
|
20
20
|
MIN_FRAME_SIZE = 8
|
21
21
|
TIMEOUT = [1, 0].pack("l_2")
|
@@ -38,9 +38,9 @@ module CanMessenger
|
|
38
38
|
# @param [Integer] id The CAN ID of the message (up to 29 bits for extended IDs).
|
39
39
|
# @param [Array<Integer>] data The data bytes of the CAN message (0 to 8 bytes).
|
40
40
|
# @return [void]
|
41
|
-
def send_can_message(id:, data:)
|
41
|
+
def send_can_message(id:, data:, extended_id: false)
|
42
42
|
with_socket do |socket|
|
43
|
-
frame = build_can_frame(id: id, data: data)
|
43
|
+
frame = build_can_frame(id: id, data: data, extended_id: extended_id)
|
44
44
|
socket.write(frame)
|
45
45
|
end
|
46
46
|
rescue StandardError => e
|
@@ -111,13 +111,16 @@ module CanMessenger
|
|
111
111
|
# @param id [Integer] the CAN ID
|
112
112
|
# @param data [Array<Integer>] up to 8 bytes
|
113
113
|
# @return [String] a 16-byte string representing a classic CAN frame
|
114
|
-
def build_can_frame(id:, data:)
|
114
|
+
def build_can_frame(id:, data:, extended_id: false)
|
115
115
|
raise ArgumentError, "CAN data cannot exceed 8 bytes" if data.size > 8
|
116
116
|
|
117
|
-
#
|
117
|
+
# Mask the ID to 29 bits
|
118
118
|
can_id = id & 0x1FFFFFFF
|
119
119
|
|
120
|
-
#
|
120
|
+
# If extended_id == true, set bit 31 (CAN_EFF_FLAG)
|
121
|
+
can_id |= 0x80000000 if extended_id
|
122
|
+
|
123
|
+
# Pack the 4‐byte ID (big-endian or little-endian)
|
121
124
|
id_bytes = @endianness == :big ? [can_id].pack("L>") : [can_id].pack("V")
|
122
125
|
|
123
126
|
# 1 byte for DLC, then 3 bytes of padding
|
@@ -126,7 +129,7 @@ module CanMessenger
|
|
126
129
|
# Up to 8 data bytes, pad with 0 if fewer
|
127
130
|
payload = data.pack("C*").ljust(8, "\x00")
|
128
131
|
|
129
|
-
# Total 16 bytes
|
132
|
+
# Total 16 bytes (4 for ID, 1 for DLC, 3 padding, 8 data)
|
130
133
|
id_bytes + dlc_and_pad + payload
|
131
134
|
end
|
132
135
|
|
@@ -166,25 +169,40 @@ module CanMessenger
|
|
166
169
|
#
|
167
170
|
# @param [String] frame
|
168
171
|
# @return [Hash, nil]
|
169
|
-
def parse_frame(frame:)
|
172
|
+
def parse_frame(frame:) # rubocop:disable Metrics/MethodLength
|
170
173
|
return nil unless frame && frame.size >= MIN_FRAME_SIZE
|
171
174
|
|
172
|
-
|
173
|
-
|
175
|
+
raw_id = unpack_frame_id(frame: frame)
|
176
|
+
|
177
|
+
# Determine if EFF bit is set
|
178
|
+
extended = raw_id.anybits?(0x80000000)
|
179
|
+
# or raw_id.anybits?(0x80000000) if your Ruby version supports `Integer#anybits?`
|
180
|
+
|
181
|
+
# Now mask off everything except the lower 29 bits
|
182
|
+
id = raw_id & 0x1FFFFFFF
|
174
183
|
|
175
184
|
# DLC is the lower 4 bits of byte 4
|
176
185
|
data_length = frame[4].ord & 0x0F
|
177
186
|
|
178
|
-
#
|
179
|
-
data =
|
180
|
-
|
187
|
+
# Extract data
|
188
|
+
data = if frame.size >= MIN_FRAME_SIZE + data_length
|
189
|
+
frame[MIN_FRAME_SIZE, data_length].unpack("C*")
|
190
|
+
else
|
191
|
+
[]
|
192
|
+
end
|
193
|
+
|
194
|
+
{ id: id, data: data, extended: extended }
|
181
195
|
rescue StandardError => e
|
182
196
|
@logger.error("Error parsing CAN frame: #{e}")
|
183
197
|
nil
|
184
198
|
end
|
185
199
|
|
186
200
|
def unpack_frame_id(frame:)
|
187
|
-
@endianness == :big
|
201
|
+
if @endianness == :big
|
202
|
+
frame[0..3].unpack1("L>")
|
203
|
+
else
|
204
|
+
frame[0..3].unpack1("V")
|
205
|
+
end
|
188
206
|
end
|
189
207
|
|
190
208
|
# Checks whether the given message ID matches the specified filter.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: can_messenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fk1018
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: CanMessenger provides an interface to send and receive messages over
|
14
14
|
the CAN bus, useful for applications requiring CAN communication in Ruby.
|