This repository has been archived by the owner on May 8, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrvc2mqtt.rb
executable file
·58 lines (49 loc) · 1.85 KB
/
rvc2mqtt.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/env ruby
#
# This command-line executable connects to a CAN bus, receives and decodes RV-C
# messages, and publishes them to an MQTT message broker.
require 'yaml'
require 'json'
require 'mqtt'
require 'open3'
require_relative 'lib/rvc_parser'
require_relative 'lib/bitmath'
mqtt_address = 'r2'
# Parse the text output of candump and decode various information as
# described in RV-C Revised Application Layer section 3.2.
#
# Sample candump line:
# (1550629697.810979) can0 19FFD442 [8] 01 02 F7 FF FF FF FF FF
def parse_candump_line(line)
columns = line.split(/\s+/)
time = columns[0].gsub(/[^0-9]/, '') # in microseconds
prio = columns[2].hex.bitrange(26..28, bytes: 8)
dgn = columns[2].hex.bitrange(8..24, bytes: 8)
dgn_str = dgn.to_s(16).upcase.rjust(5, '0') # Change back to hex, e.g "0E1F7"
src = columns[2].hex.bitrange(0..7, bytes: 8)
len = columns[3].gsub(/[^0-9]/, '').to_i # number of data bytes
data = columns[4..(4+len)].join()
{ time: time, prio: prio, dgn: dgn_str, src: src, len: len, data: data }
end
#
# Main program entry
#
rvc_spec = RVCParser.new
mqtt = MQTT::Client.connect(host: mqtt_address)
# Publish rvc_spec version number
api_version = rvc_spec.api_version
mqtt.publish('rvc/api_version', api_version, true)
# Monitor the canbus, decode each line, and publish the results to mqtt.
Open3.popen3('/usr/bin/candump -ta can0') do |stdin, stdout, stderr, wait_thr|
while line = stdout.gets.strip do
message = parse_candump_line(line)
decoded = rvc_spec.decode(message[:dgn], message[:data])
decoded['timestamp'] = message[:time]
topic = 'rvc/' + decoded['name']
topic += '/' + decoded['instance'].to_s if decoded['instance']
mqtt.publish(topic + '/json', decoded.sort.to_h.to_json, false)
decoded.each do | key, value |
mqtt.publish(topic + '/' + key, value, false)
end
end
end