automotive-ecu 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/bin/bundle +114 -0
- data/bin/coderay +29 -0
- data/bin/console +14 -0
- data/bin/htmldiff +29 -0
- data/bin/irb +29 -0
- data/bin/ldiff +29 -0
- data/bin/pry +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/setup +8 -0
- data/lib/core_ext.rb +69 -0
- data/lib/ecu/combined_list.rb +25 -0
- data/lib/ecu/combined_list_comparison.rb +50 -0
- data/lib/ecu/interfaces/a2l/label_list.rb +18 -0
- data/lib/ecu/interfaces/a2l/signal_list.rb +15 -0
- data/lib/ecu/interfaces/dbc/signal_list.rb +12 -0
- data/lib/ecu/interfaces/dcm/buffer.rb +39 -0
- data/lib/ecu/interfaces/dcm/festkennfeld.rb +9 -0
- data/lib/ecu/interfaces/dcm/festkennlinie.rb +9 -0
- data/lib/ecu/interfaces/dcm/festwert.rb +20 -0
- data/lib/ecu/interfaces/dcm/festwerteblock.rb +26 -0
- data/lib/ecu/interfaces/dcm/functions.rb +13 -0
- data/lib/ecu/interfaces/dcm/gruppenkennfeld.rb +9 -0
- data/lib/ecu/interfaces/dcm/gruppenkennlinie.rb +9 -0
- data/lib/ecu/interfaces/dcm/kennfeld.rb +32 -0
- data/lib/ecu/interfaces/dcm/kennlinie.rb +25 -0
- data/lib/ecu/interfaces/dcm/label.rb +25 -0
- data/lib/ecu/interfaces/dcm/label_list.rb +94 -0
- data/lib/ecu/interfaces/dcm/malformed_dcm_error.rb +34 -0
- data/lib/ecu/interfaces/dcm/property_parser.rb +51 -0
- data/lib/ecu/interfaces/dcm/stuetzstellenverteilung.rb +20 -0
- data/lib/ecu/interfaces/lab/combined_list.rb +32 -0
- data/lib/ecu/interfaces/lab/lab_parser.rb +61 -0
- data/lib/ecu/interfaces/lab/label.rb +21 -0
- data/lib/ecu/interfaces/lab/label_list.rb +29 -0
- data/lib/ecu/interfaces/lab/signal.rb +15 -0
- data/lib/ecu/interfaces/lab/signal_list.rb +29 -0
- data/lib/ecu/interfaces/mfile/festwert.rb +10 -0
- data/lib/ecu/interfaces/mfile/festwerteblock.rb +12 -0
- data/lib/ecu/interfaces/mfile/kennfeld.rb +12 -0
- data/lib/ecu/interfaces/mfile/kennlinie.rb +7 -0
- data/lib/ecu/interfaces/mfile/label_list.rb +13 -0
- data/lib/ecu/interfaces/mfile/stuetzstellenverteilung.rb +7 -0
- data/lib/ecu/labels/festwert.rb +58 -0
- data/lib/ecu/labels/festwerteblock.rb +80 -0
- data/lib/ecu/labels/interpolator.rb +55 -0
- data/lib/ecu/labels/kennfeld.rb +107 -0
- data/lib/ecu/labels/kennlinie.rb +84 -0
- data/lib/ecu/labels/label.rb +82 -0
- data/lib/ecu/labels/label_list.rb +137 -0
- data/lib/ecu/labels/label_list_comparison.rb +65 -0
- data/lib/ecu/labels/stuetzstellenverteilung.rb +65 -0
- data/lib/ecu/labels/value_comparison.rb +37 -0
- data/lib/ecu/labels/value_printer.rb +49 -0
- data/lib/ecu/labels.rb +2 -0
- data/lib/ecu/signals/signal.rb +73 -0
- data/lib/ecu/signals/signal_list.rb +68 -0
- data/lib/ecu/signals/signal_list_comparison.rb +52 -0
- data/lib/ecu/signals.rb +2 -0
- data/lib/ecu/version.rb +3 -0
- data/lib/ecu.rb +59 -0
- metadata +161 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class Ecu
|
2
|
+
class Kennfeld < Label
|
3
|
+
def self.dcm_header
|
4
|
+
%r{^KENNFELD\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)\s+(?<ydim>\d+)}
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_dcm
|
8
|
+
"#{type.upcase} #{name} #{xdim} #{ydim}\n".tap do |str|
|
9
|
+
str << " LANGNAME #{description.enquote}\n" if description
|
10
|
+
str << " FUNKTION #{function}\n" if function
|
11
|
+
str << " EINHEIT_X #{xunit.enquote}\n" if xunit
|
12
|
+
str << " EINHEIT_Y #{yunit.enquote}\n" if yunit
|
13
|
+
str << " EINHEIT_W #{unit.enquote}\n" if unit
|
14
|
+
str << case xvalue.first
|
15
|
+
when Numeric then " ST/X #{xvalue.join(" ")}\n"
|
16
|
+
when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
|
17
|
+
end
|
18
|
+
yvalue.each_with_index do |entry, idx|
|
19
|
+
str << case entry
|
20
|
+
when Numeric then " ST/Y #{entry}\n"
|
21
|
+
when String then " ST_TX/Y #{entry.enquote}\n"
|
22
|
+
end
|
23
|
+
str << case value[idx].first
|
24
|
+
when Numeric then " WERT #{value[idx].join(" ")}\n"
|
25
|
+
when String then " TEXT #{value[idx].map(&:enquote).join(" ")}\n"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
str << "END\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Ecu
|
2
|
+
class Kennlinie < Label
|
3
|
+
def self.dcm_header
|
4
|
+
%r{^KENNLINIE\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)}
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_dcm
|
8
|
+
"#{type.upcase} #{name} #{xdim}\n".tap do |str|
|
9
|
+
str << " LANGNAME #{description.enquote}\n" if description
|
10
|
+
str << " FUNKTION #{function}\n" if function
|
11
|
+
str << " EINHEIT_X #{xunit.enquote}\n" if xunit
|
12
|
+
str << " EINHEIT_W #{unit.enquote}\n" if unit
|
13
|
+
str << case xvalue.first
|
14
|
+
when Numeric then " ST/X #{xvalue.join(" ")}\n"
|
15
|
+
when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
|
16
|
+
end
|
17
|
+
str << case value.first
|
18
|
+
when Numeric then " WERT #{value.join(" ")}\n"
|
19
|
+
when String then " TEXT #{value.map(&:enquote).join(" ")}\n"
|
20
|
+
end
|
21
|
+
str << "END\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "property_parser"
|
2
|
+
|
3
|
+
class Ecu
|
4
|
+
class Label
|
5
|
+
def self.from_dcm(input)
|
6
|
+
lines = case input
|
7
|
+
in Array then input
|
8
|
+
in String then input.lines
|
9
|
+
end
|
10
|
+
hsh = dcm_header.extract_captures(lines.first)
|
11
|
+
|
12
|
+
hsh[:xdim] = hsh[:xdim].to_i if hsh.key?(:xdim)
|
13
|
+
hsh[:ydim] = hsh[:ydim].to_i if hsh.key?(:ydim)
|
14
|
+
|
15
|
+
fail "Malformed DCM" if hsh.empty?
|
16
|
+
fail "Malformed DCM" unless lines.last.match?(/^END$/)
|
17
|
+
|
18
|
+
lines[1..-2]
|
19
|
+
.map { DcmPropertyParser.call(_1) }
|
20
|
+
.each { hsh.merge!(_1) { |_, old, new| old + new } }
|
21
|
+
|
22
|
+
new(**hsh)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative "functions"
|
2
|
+
require_relative "festwert"
|
3
|
+
require_relative "festwerteblock"
|
4
|
+
require_relative "kennlinie"
|
5
|
+
require_relative "gruppenkennlinie"
|
6
|
+
require_relative "festkennlinie"
|
7
|
+
require_relative "kennfeld"
|
8
|
+
require_relative "gruppenkennfeld"
|
9
|
+
require_relative "festkennfeld"
|
10
|
+
require_relative "stuetzstellenverteilung"
|
11
|
+
require_relative "malformed_dcm_error"
|
12
|
+
require_relative "buffer"
|
13
|
+
|
14
|
+
class Ecu
|
15
|
+
class LabelList
|
16
|
+
|
17
|
+
DCM_HEADER = "KONSERVIERUNG_FORMAT 2.0"
|
18
|
+
BLANKLINE_REGEX = /^\s*$/
|
19
|
+
COMMENT_REGEX = /^\*.*/
|
20
|
+
|
21
|
+
def self.from_dcm(str)
|
22
|
+
buffer = DcmBuffer.new
|
23
|
+
headers = []
|
24
|
+
subheaders = []
|
25
|
+
functions = []
|
26
|
+
labels = {}
|
27
|
+
|
28
|
+
str.each_line.lazy.with_index(1).each do |line, n|
|
29
|
+
line = normalize_whitespace(line)
|
30
|
+
case line
|
31
|
+
when BLANKLINE_REGEX then next
|
32
|
+
when COMMENT_REGEX
|
33
|
+
case buffer.header
|
34
|
+
when :pre then headers << line[1..].strip
|
35
|
+
when :after then subheaders << line[1..].strip
|
36
|
+
when :done then # Header time over, do nothing
|
37
|
+
end
|
38
|
+
when DCM_HEADER then buffer.header_seen!
|
39
|
+
when Functions.dcm_header then buffer.start!(Functions, [line])
|
40
|
+
when Festwert.dcm_header then buffer.start!(Festwert, [line])
|
41
|
+
when Festwerteblock.dcm_header then buffer.start!(Festwerteblock, [line])
|
42
|
+
when Kennlinie.dcm_header then buffer.start!(Kennlinie, [line])
|
43
|
+
when Gruppenkennlinie.dcm_header then buffer.start!(Gruppenkennlinie, [line])
|
44
|
+
when Festkennlinie.dcm_header then buffer.start!(Festkennlinie, [line])
|
45
|
+
when Kennfeld.dcm_header then buffer.start!(Kennfeld, [line])
|
46
|
+
when Gruppenkennfeld.dcm_header then buffer.start!(Gruppenkennfeld, [line])
|
47
|
+
when Festkennfeld.dcm_header then buffer.start!(Festkennfeld, [line])
|
48
|
+
when Stuetzstellenverteilung.dcm_header then buffer.start!(Stuetzstellenverteilung, [line])
|
49
|
+
when "END" then
|
50
|
+
case obj = buffer.finish!(line)
|
51
|
+
when Label
|
52
|
+
fail "Duplicate label #{obj.name}" unless labels[obj.name].nil?
|
53
|
+
|
54
|
+
labels[obj.name] = obj
|
55
|
+
when Functions
|
56
|
+
fail "Duplicate functions definition" unless functions.empty?
|
57
|
+
|
58
|
+
functions = obj
|
59
|
+
else
|
60
|
+
fail "Unknown object #{obj}"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
buffer.append!(line)
|
64
|
+
end
|
65
|
+
rescue RuntimeError => e
|
66
|
+
raise MalformedDcmError.new(e.message, n, str), e.message
|
67
|
+
end
|
68
|
+
|
69
|
+
new(labels.values, headers, subheaders, true)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.normalize_whitespace(line)
|
73
|
+
line.chomp.gsub(/[[:space:]]/, " ").rstrip
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_dcm
|
77
|
+
out = []
|
78
|
+
|
79
|
+
unless headers.empty?
|
80
|
+
out += headers.map { "* " + _1 }.push("")
|
81
|
+
end
|
82
|
+
|
83
|
+
out << DCM_HEADER << ""
|
84
|
+
|
85
|
+
unless subheaders.empty?
|
86
|
+
out += subheaders.map { "* " + _1 }.push("")
|
87
|
+
end
|
88
|
+
|
89
|
+
out += map(&:to_dcm)
|
90
|
+
|
91
|
+
out.join("\n")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Ecu
|
2
|
+
class MalformedDcmError < StandardError
|
3
|
+
attr_reader :lineno, :filecontent
|
4
|
+
def initialize(msg, lineno, filecontent)
|
5
|
+
super(msg)
|
6
|
+
@lineno = lineno
|
7
|
+
@filecontent = filecontent
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s = "Malformed DCM: #{super} near line ##{lineno}"
|
11
|
+
def to_str = to_s
|
12
|
+
|
13
|
+
def context
|
14
|
+
filecontent
|
15
|
+
.lines
|
16
|
+
.each
|
17
|
+
.with_index(1)
|
18
|
+
.map { |line, n| present(line, n, n == lineno) }
|
19
|
+
.then { _1[ctx_startline..ctx_endline] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def present(line, n, highlight)
|
23
|
+
case highlight
|
24
|
+
when true then fmt(n) + " => | " + line
|
25
|
+
when false then fmt(n) + " | " + line
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def ctx_startline = [0, lineno - 7].max
|
30
|
+
def ctx_endline = @endline ||= [filecontent.lines.count - 1, lineno + 3].min
|
31
|
+
def fmt_str = "%#{(ctx_endline + 1).to_s.length}d"
|
32
|
+
def fmt(n) = fmt_str % n
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Ecu
|
2
|
+
class DcmPropertyParser
|
3
|
+
|
4
|
+
def self.call(line)
|
5
|
+
key, _, value = line.strip.partition(/\s+/)
|
6
|
+
eval_property(key, value)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def self.eval_property(key, value)
|
12
|
+
case key
|
13
|
+
when "ST/X" then { xvalue: numeric_array(value) }
|
14
|
+
when "ST/Y" then { yvalue: numeric_array(value) }
|
15
|
+
when "WERT" then { value: numeric_array(value) }
|
16
|
+
when "ST_TX/X" then { xvalue: string_array(value) }
|
17
|
+
when "ST_TX/Y" then { yvalue: string_array(value) }
|
18
|
+
when "TEXT" then { value: string_array(value) }
|
19
|
+
when "FUNKTION" then { function: value }
|
20
|
+
when "EINHEIT_X" then { xunit: string_value(value) }
|
21
|
+
when "EINHEIT_Y" then { yunit: string_value(value) }
|
22
|
+
when "EINHEIT_W" then { unit: string_value(value) }
|
23
|
+
when "LANGNAME" then { description: string_value(value) }
|
24
|
+
when "DISPLAYNAME" then { }
|
25
|
+
else fail ArgumentError, "Unknown key #{key}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.string_value(str)
|
30
|
+
str.delete_surrounding('"')
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.numeric_array(str)
|
34
|
+
str.split.map { Float(_1) rescue Label::InvalidValue.new(_1) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.string_array(str)
|
38
|
+
str.scan(/"([^"]*)"/).flatten
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
class Label
|
44
|
+
InvalidValue = Struct.new(:value) do
|
45
|
+
def to_s
|
46
|
+
"<InvalidValue: \"#{value}\">"
|
47
|
+
end
|
48
|
+
def inspect; to_s; end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Ecu
|
2
|
+
class Stuetzstellenverteilung < Label
|
3
|
+
def self.dcm_header
|
4
|
+
%r{STUETZSTELLENVERTEILUNG\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)}
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_dcm
|
8
|
+
"#{type.upcase} #{name} #{xdim}\n".tap do |str|
|
9
|
+
str << " LANGNAME #{description.enquote}\n" if description
|
10
|
+
str << " FUNKTION #{function}\n" if function
|
11
|
+
str << " EINHEIT_X #{xunit.enquote}\n" if xunit
|
12
|
+
str << case xvalue.first
|
13
|
+
when Numeric then " ST/X #{xvalue.join(" ")}\n"
|
14
|
+
when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
|
15
|
+
end
|
16
|
+
str << "END\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "signal_list"
|
2
|
+
require_relative "label_list"
|
3
|
+
|
4
|
+
class Ecu
|
5
|
+
class CombinedList
|
6
|
+
def self.from_lab(str)
|
7
|
+
signals, labels, headers, subheaders = LabParser.call(str)
|
8
|
+
new(signals, labels, headers, subheaders)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_lab
|
12
|
+
out = []
|
13
|
+
|
14
|
+
out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
|
15
|
+
|
16
|
+
out.append("[SETTINGS]")
|
17
|
+
out.append("Version;V1.1")
|
18
|
+
out.append("MultiRasterSeparator;&")
|
19
|
+
out.append("")
|
20
|
+
|
21
|
+
out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
|
22
|
+
|
23
|
+
out.append("[RAMCELL]")
|
24
|
+
out.append(*signals.map(&:to_lab))
|
25
|
+
|
26
|
+
out.append("[Label]")
|
27
|
+
out.append(*labels.map(&:to_lab))
|
28
|
+
|
29
|
+
out.join("\n")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative "../../labels"
|
2
|
+
require_relative "../../signals"
|
3
|
+
|
4
|
+
class LabParser
|
5
|
+
def self.call(str)
|
6
|
+
lines = str.lines
|
7
|
+
|
8
|
+
[
|
9
|
+
extract_signals(block_bounded_by(lines, "[RAMCELL]", /\A\[/)),
|
10
|
+
extract_labels(block_bounded_by(lines, "[Label]", /\A\[/)),
|
11
|
+
extract_headers(block_bounded_by(lines, 0, "[SETTINGS]")),
|
12
|
+
extract_headers(block_bounded_by(lines, "[SETTINGS]", /\A\[/)),
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.extract_labels(lines)
|
17
|
+
Ecu::LabelList.new lines.
|
18
|
+
reject { |l| l.blank? }.
|
19
|
+
reject { |l| l.start_with?(";") }.
|
20
|
+
map { |l| Ecu::Label.from_lab(l) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.extract_signals(lines)
|
24
|
+
Ecu::SignalList.new lines.
|
25
|
+
reject { |l| l.blank? }.
|
26
|
+
reject { |l| l.start_with?(";") }.
|
27
|
+
map { |l| Ecu::Signal.from_lab(l) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.extract_headers(lines)
|
31
|
+
lines.
|
32
|
+
select { |l| l.match(/\A; /) }.
|
33
|
+
map { |l| l[2..-1].chomp }
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.block_bounded_by(lines, upper, lower)
|
37
|
+
upper = case upper
|
38
|
+
when Integer then upper
|
39
|
+
when String
|
40
|
+
return [] unless lines.any? { |l| l.strip.downcase == upper.downcase }
|
41
|
+
lines.index { |l| l.strip.downcase == upper.downcase } + 1
|
42
|
+
when Regexp
|
43
|
+
return [] unless lines.any? { |l| l.match?(upper) }
|
44
|
+
lines.index { |l| l.match?(upper) } + 1
|
45
|
+
end
|
46
|
+
|
47
|
+
segment = lines[upper..-1]
|
48
|
+
|
49
|
+
lower = case lower
|
50
|
+
when Integer then lower
|
51
|
+
when String
|
52
|
+
return lines[upper..-1] unless segment.any? { |l| l.strip.downcase == lower.downcase }
|
53
|
+
upper + segment.index { |l| l.strip.downcase == lower.downcase }
|
54
|
+
when Regexp
|
55
|
+
return lines[upper..-1] unless segment.any? { |l| l.match?(lower) }
|
56
|
+
upper + segment.index { |l| l.match?(lower) }
|
57
|
+
end
|
58
|
+
|
59
|
+
lines[upper...lower]
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Ecu
|
2
|
+
class Label
|
3
|
+
|
4
|
+
# This is a silly hack, since the *.lab file doesn't contain any information
|
5
|
+
# about the label in question (just the name). Subsequently, just initialize
|
6
|
+
# a Festwert with no value and hope if does the job correctly
|
7
|
+
|
8
|
+
def self.from_lab(line)
|
9
|
+
name, description = line.strip.split(";")
|
10
|
+
if description.nil?
|
11
|
+
Festwert.new(name: name, value: nil)
|
12
|
+
else
|
13
|
+
Festwert.new(name: name, value: nil, description: description)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_lab
|
18
|
+
"#{name};#{description}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "../../../core_ext"
|
2
|
+
require_relative "lab_parser"
|
3
|
+
|
4
|
+
class Ecu
|
5
|
+
class LabelList
|
6
|
+
def self.from_lab(str)
|
7
|
+
_, labels, headers, subheaders = LabParser.call(str)
|
8
|
+
new(labels, headers, subheaders)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_lab
|
12
|
+
out = []
|
13
|
+
|
14
|
+
out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
|
15
|
+
|
16
|
+
out.append("[SETTINGS]")
|
17
|
+
out.append("Version;V1.1")
|
18
|
+
out.append("MultiRasterSeparator;&")
|
19
|
+
out.append("")
|
20
|
+
|
21
|
+
out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
|
22
|
+
|
23
|
+
out.append("[Label]")
|
24
|
+
out.append(*map(&:to_lab))
|
25
|
+
|
26
|
+
out.join("\n")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Ecu
|
2
|
+
class Signal
|
3
|
+
def self.from_lab(line)
|
4
|
+
name, tasks, comment = line.strip.split(";")
|
5
|
+
maintask = tasks.split("&").first rescue nil
|
6
|
+
new(name: name,
|
7
|
+
task: maintask,
|
8
|
+
description: comment&.strip)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_lab
|
12
|
+
"#{name};#{task};#{description}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "../../../core_ext"
|
2
|
+
require_relative "lab_parser"
|
3
|
+
|
4
|
+
class Ecu
|
5
|
+
class SignalList
|
6
|
+
def self.from_lab(str)
|
7
|
+
signals, _, headers, subheaders = LabParser.call(str)
|
8
|
+
new(signals, headers, subheaders)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_lab
|
12
|
+
out = []
|
13
|
+
|
14
|
+
out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
|
15
|
+
|
16
|
+
out.append("[SETTINGS]")
|
17
|
+
out.append("Version;V1.1")
|
18
|
+
out.append("MultiRasterSeparator;&")
|
19
|
+
out.append("")
|
20
|
+
|
21
|
+
out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
|
22
|
+
|
23
|
+
out.append("[RAMCELL]")
|
24
|
+
out.append(*map(&:to_lab))
|
25
|
+
|
26
|
+
out.join("\n")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative "festwert"
|
2
|
+
require_relative "festwerteblock"
|
3
|
+
require_relative "kennlinie"
|
4
|
+
require_relative "kennfeld"
|
5
|
+
require_relative "stuetzstellenverteilung"
|
6
|
+
|
7
|
+
class Ecu
|
8
|
+
class LabelList
|
9
|
+
def to_mfile
|
10
|
+
self.map(&:to_mfile).join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative "label"
|
2
|
+
|
3
|
+
class Ecu
|
4
|
+
class Festwert < Label
|
5
|
+
|
6
|
+
attr_reader :value, :unit
|
7
|
+
|
8
|
+
def initialize(name:,
|
9
|
+
value:,
|
10
|
+
unit: nil,
|
11
|
+
function: nil,
|
12
|
+
description: nil)
|
13
|
+
@name = name
|
14
|
+
@value = value.is_a?(Array) ? value.first : value
|
15
|
+
@unit = unit
|
16
|
+
@function = function
|
17
|
+
@description = description
|
18
|
+
end
|
19
|
+
|
20
|
+
def round_to(n)
|
21
|
+
return self unless value.is_a?(Numeric)
|
22
|
+
self.with \
|
23
|
+
value: value.round(n)
|
24
|
+
end
|
25
|
+
|
26
|
+
def bytesize
|
27
|
+
BYTESIZE[:number]
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s(detail: false)
|
31
|
+
if detail == :justvalue
|
32
|
+
value.to_s
|
33
|
+
elsif detail == :value
|
34
|
+
"#{name}: #{value}"
|
35
|
+
elsif detail == :onelinefull
|
36
|
+
"#{name}: #{to_s(detail: :oneline)}"
|
37
|
+
elsif detail == :oneline
|
38
|
+
"#{value}"
|
39
|
+
elsif detail
|
40
|
+
<<~EOS
|
41
|
+
#{name}: #{type}
|
42
|
+
Value: #{value}
|
43
|
+
Unit: "#{unit}"
|
44
|
+
EOS
|
45
|
+
else
|
46
|
+
"#{name}: #{type}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def properties
|
51
|
+
[:name, :value, :unit, :function, :description]
|
52
|
+
end
|
53
|
+
|
54
|
+
def equality_properties
|
55
|
+
[:name, :value]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|