can_messenger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CanMessenger
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,9 @@
1
+ # lib/can_messenger.rb
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "can_messenger/version"
5
+ require_relative "can_messenger/messenger"
6
+
7
+ module CanMessenger
8
+ class Error < StandardError; end
9
+ 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: []