can_messenger 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +95 -0
- data/lib/can_messenger/messenger.rb +119 -0
- data/lib/can_messenger/version.rb +5 -0
- data/lib/can_messenger.rb +9 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6aab35f0ccd4fcbd716ddb9cb553555c1c524eef3ca917d5cf43539b8bb55ff0
|
4
|
+
data.tar.gz: 1f2ebb1af8cf741ceba5c1e2033faa807ed4f8f58e1c44dcbacfe7adba60a9dc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4f20347545fdfa495b80fc7475e611e0aa80bcc47a8a4bca26844f07a677327949001dd28b24422a402a49bd864ce2ecdde00968cc0ee9f150da4a968d1617a6
|
7
|
+
data.tar.gz: 712bbb367ea096d2a9e57d1649bafb75c90b51652a789a907cdc1f8984ea965959b24f46ac083340816364ac023cf0efae10c1b7e378f4535c40e3324045f248
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# CanMessenger
|
2
|
+
|
3
|
+
`can_messenger` is a Ruby gem that provides an interface for communicating over the CAN bus, allowing users to send and receive CAN messages. This gem is designed for developers who need an easy way to interact with CAN-enabled devices.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
This gem relies on `cansend` from the `can-utils` package, which is typically available on Linux-based systems. Make sure to install `can-utils` before using `can_messenger`:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
sudo apt-get install can-utils
|
11
|
+
```
|
12
|
+
|
13
|
+
To install `can_messenger`, add it to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'can_messenger'
|
17
|
+
```
|
18
|
+
|
19
|
+
Then execute:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
bundle install
|
23
|
+
```
|
24
|
+
|
25
|
+
Or install it yourself with:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
gem install can_messenger
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
### Initializing the Messenger
|
34
|
+
|
35
|
+
To create a new instance of `CanMessenger` and start sending messages:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'can_messenger'
|
39
|
+
|
40
|
+
messenger = CanMessenger::Messenger.new('can0')
|
41
|
+
```
|
42
|
+
|
43
|
+
### Sending CAN Messages
|
44
|
+
|
45
|
+
To send a message:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
messenger.send_can_message(0x123, [0xDE, 0xAD, 0xBE, 0xEF])
|
49
|
+
```
|
50
|
+
|
51
|
+
### Receiving CAN Messages
|
52
|
+
|
53
|
+
To listen for incoming messages, set up a listener:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
messenger.start_listening do |message|
|
57
|
+
puts "Received: ID=#{message[:id]}, Data=#{message[:data]}"
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
### Stopping the Listener
|
62
|
+
|
63
|
+
To stop listening, use:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
messenger.stop_listening
|
67
|
+
```
|
68
|
+
|
69
|
+
## Features
|
70
|
+
|
71
|
+
- **Send CAN Messages**: Send data to specified CAN IDs.
|
72
|
+
- **Receive CAN Messages**: Continuously listen for messages on a CAN interface.
|
73
|
+
- **Logging**: Logs errors and events for debugging and troubleshooting.
|
74
|
+
|
75
|
+
## Development
|
76
|
+
|
77
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
78
|
+
|
79
|
+
To install this gem onto your local machine, run:
|
80
|
+
|
81
|
+
```bash
|
82
|
+
bundle exec rake install
|
83
|
+
```
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/fk1018/can_messenger](https://github.com/fk1018/can_messenger).
|
88
|
+
|
89
|
+
## License
|
90
|
+
|
91
|
+
The gem is available as open-source under the terms of the MIT License.
|
92
|
+
|
93
|
+
## Author
|
94
|
+
|
95
|
+
Developed by Fredrick Khoury.
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# lib/can_messenger/messenger.rb
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "socket"
|
5
|
+
require "logger"
|
6
|
+
|
7
|
+
module CanMessenger
|
8
|
+
# Messenger
|
9
|
+
#
|
10
|
+
# This class provides an interface to send and receive CAN bus messages.
|
11
|
+
# It supports sending messages with specific CAN IDs and listening for incoming messages.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# socket = CanMessenger::Messenger.new('can0')
|
15
|
+
# socket.send_can_message(0x123, [0xDE, 0xAD, 0xBE, 0xEF])
|
16
|
+
# socket.start_listening do |message|
|
17
|
+
# puts "Received: ID=#{message[:id]}, Data=#{message[:data].map { |b| '0x%02X' % b }}"
|
18
|
+
# end
|
19
|
+
class Messenger
|
20
|
+
# Initializes a new Messenger instance.
|
21
|
+
#
|
22
|
+
# @param [String] can_interface The CAN interface to use (e.g., 'can0').
|
23
|
+
# @param [Logger] logger Optional logger for error handling and debug information.
|
24
|
+
def initialize(can_interface, logger = nil)
|
25
|
+
@can_interface = can_interface
|
26
|
+
@logger = logger || Logger.new($stdout)
|
27
|
+
@listening = true # Control flag for listening loop
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sends a CAN message using the `cansend` command.
|
31
|
+
#
|
32
|
+
# @param [Integer] id The CAN ID of the message.
|
33
|
+
# @param [Array<Integer>] data The data bytes of the CAN message.
|
34
|
+
# @return [void]
|
35
|
+
def send_can_message(id, data)
|
36
|
+
hex_id = format("%03X", id)
|
37
|
+
hex_data = data.map { |byte| format("%02X", byte) }.join
|
38
|
+
command = "cansend #{@can_interface} #{hex_id}##{hex_data}"
|
39
|
+
system(command)
|
40
|
+
rescue StandardError => e
|
41
|
+
@logger.error("Error sending CAN message (ID: #{id}): #{e}")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Continuously listens for CAN messages on the specified interface.
|
45
|
+
#
|
46
|
+
# Yields each message as a hash with keys :id and :data.
|
47
|
+
# @yield [Hash] Each received message in the format { id: Integer, data: Array<Integer> }.
|
48
|
+
# @return [void]
|
49
|
+
def start_listening
|
50
|
+
@logger.info("Started listening on #{@can_interface}")
|
51
|
+
socket = create_socket
|
52
|
+
while @listening
|
53
|
+
message = receive_message(socket)
|
54
|
+
break unless message # Exit loop if no message
|
55
|
+
|
56
|
+
yield(message)
|
57
|
+
end
|
58
|
+
ensure
|
59
|
+
socket&.close
|
60
|
+
end
|
61
|
+
|
62
|
+
# Stops the listening loop by setting @listening to false.
|
63
|
+
#
|
64
|
+
# This method can be called from an external thread or signal handler.
|
65
|
+
# @return [void]
|
66
|
+
def stop_listening
|
67
|
+
@listening = false
|
68
|
+
@logger.info("Stopped listening on #{@can_interface}")
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Creates and configures a CAN socket.
|
74
|
+
#
|
75
|
+
# @return [Socket] The configured CAN socket.
|
76
|
+
def create_socket
|
77
|
+
socket = Socket.open(Socket::PF_CAN, Socket::SOCK_RAW, Socket::CAN_RAW)
|
78
|
+
socket.bind(Socket.pack_sockaddr_can(@can_interface))
|
79
|
+
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [1, 0].pack("l_2"))
|
80
|
+
socket
|
81
|
+
rescue StandardError => e
|
82
|
+
@logger.error("Error creating CAN socket on interface #{@can_interface}: #{e}")
|
83
|
+
end
|
84
|
+
|
85
|
+
# Receives a CAN message from the socket and parses it.
|
86
|
+
#
|
87
|
+
# @param [Socket] socket The CAN socket to read from.
|
88
|
+
# @return [Hash, nil] Parsed message in the format { id: Integer, data: Array<Integer> },
|
89
|
+
# or nil if no message is received or an error occurs.
|
90
|
+
def receive_message(socket)
|
91
|
+
frame = socket.recv(16)
|
92
|
+
return nil if frame.nil? || frame.size < 8
|
93
|
+
|
94
|
+
parse_frame(frame)
|
95
|
+
rescue IO::WaitReadable
|
96
|
+
nil
|
97
|
+
rescue StandardError => e
|
98
|
+
@logger.error("Error receiving CAN message on interface #{@can_interface}: #{e}")
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
# Parses a raw CAN frame into a message hash.
|
103
|
+
#
|
104
|
+
# @param [String] frame The raw CAN frame.
|
105
|
+
# @return [Hash, nil] Parsed message with :id and :data keys, or nil if the frame is incomplete.
|
106
|
+
def parse_frame(frame)
|
107
|
+
return nil unless frame && frame.size >= 8
|
108
|
+
|
109
|
+
id = frame[0..3].unpack1("L>") & 0x1FFFFFFF
|
110
|
+
data_length = frame[4].ord & 0x0F
|
111
|
+
data = (frame[8, data_length].unpack("C*") if frame.size >= 8 + data_length)
|
112
|
+
|
113
|
+
{ id: id, data: data }
|
114
|
+
rescue StandardError => e
|
115
|
+
@logger.error("Error parsing CAN frame: #{e}")
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: can_messenger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- fk1018
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: CanMessenger provides an interface to send and receive messages over
|
14
|
+
the CAN bus, useful for applications requiring CAN communication in Ruby.
|
15
|
+
email:
|
16
|
+
- fk1018@users.noreply.github.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- lib/can_messenger.rb
|
23
|
+
- lib/can_messenger/messenger.rb
|
24
|
+
- lib/can_messenger/version.rb
|
25
|
+
homepage: https://github.com/fk1018/can_messenger
|
26
|
+
licenses:
|
27
|
+
- MIT
|
28
|
+
metadata:
|
29
|
+
allowed_push_host: https://rubygems.org
|
30
|
+
homepage_uri: https://github.com/fk1018/can_messenger
|
31
|
+
source_code_uri: https://github.com/fk1018/can_messenger
|
32
|
+
changelog_uri: https://github.com/fk1018/can_messenger/CHANGELOG.md
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 3.0.0
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubygems_version: 3.5.22
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: A simple Ruby wrapper to read and write CAN bus messages.
|
52
|
+
test_files: []
|